mysql 接受来自多个客户端的请求,多个线程可能同时访问同一行数据。
可分为读读并发、读写并发、写读并发、写写并发等。
并发事务存在的异常现象,需要结合 buffer pool 缓存页来看。
异常现象
脏写:一个事务更新了另一个事务未提交的数据。
事务A和事务B同时更新一条数据x0,事务A先将值更新为x1,事务B将其更新为x2,然后事务A回滚,导致x2丢失。
脏读:一个事务读取了另一个事务未提交的数据。
不可重复读:虽然一个事务无法读到别的事务未提交的值,但是可能存在事务前后读到的值不一致,因为中间一个事务修改了数据并提交。
幻读:就是一个事务查询的多行记录,然后查询的结果前后不一样。
比如一个事务先后两次查询了 id > 10 的记录,然后另一个事务在中间删除/插入了记录,并且提交,导致两次查询的结果不一致。
ANSI SQL标准的隔离级别
read uncommitted
read committed
repeatable read
serializable
读未提交:允许脏读,不允许脏写。不能修改别的事务未提交的更改,但是可以读到更改的数据。
读已提交:不允许脏读。不允许读取/修改别的事务未提交的更改。
可重复读:事务开始后,多次查询多行记录的结果是一样的。但是可能存在幻读(查询多行数据)
可串行化:!!!!!!!!!!!!!不是
MySQL 的 RR 级别
mysql 的 rr 级别 和 SQL 标准的隔离级别并不同!
spring配置事务时,可以设置isolation=Isolation.Default。
undo log 版本链
多个事务串行执行,会形成 undo log 版本链。roll_pointer 和 trx_id。
tx A插入一条记录:
tx B修改了记录:
tx C修改了记录:(隐藏的字段 trx_id 一直在变化)
基于 ReadView 实现 RC
在RC隔离级别,可以读到别的事务提交的修改。
此隔离级别存在不可重复读、幻读的问题。
生成ReadView以后开启的事务,修改了数据并提交。这部分是读取不到的。
在 RC 隔离级别下,每次查询都会生成一个 ReadView!
前后查询时,生成的 ReadView的活跃列表发生了变化。
ReadView 的格式
- m_ids,此时有哪些事务在MySQL里执行还没提交的事务;
- min_trx_id,就是m_ids里最小的值;
- max_trx_id,这是说MySQL下一个要生成的事务id,就是最大事务id;
- creator_trx_id,就是当前事务的id
第一次查询时,可能事务B的修改还未提交,此时生成的 ReadView 活跃列表包含事务B,因此读不到修改的值。会沿着版本链,找到<= min trx id 的trx_id,读取记录。
第二次查询时,事务B提交,此时生成的 ReadView 活跃列表包含不事务B,因此可以读到修改的值。
如何实现 RR
MySQL 的 RR 隔离级别可以避免不可重复读和幻读。
如何避免不可重复读?
还是依赖 ReadView 和 undo 版本链。
通过比较活跃事务 id 和 undo 版本的trx_id,来判断是否能读取该条记录。
因为一旦有事务修改数据并提交,必然会在 undo 版本链中加一条记录。
虽然 ReadView 不会发生变化,但是 undo 的 trx_id 是活跃事务,记录不会被读取。
RR 隔离级别不能完全解决幻读
注意!这里每次查询并没有重新生成 ReadView(和 RC隔离级别有所不同的一点!)
事务 A 查询两次,可能事务B处于ReadView的活跃列表,因此不会被读取。
事务C提交记录的 trx_id大于max_trx_id,因此也不会被读取。

总结
脏写:两个事务更新同一行数据,结果一个事务回滚,覆盖另一个事务的修改。
脏读,事务A读到了事务B未提交的修改的数据。
不可重复读:多次读同一条记录,读到的值不同。
幻读:多次范围查询时,别的事务插入了新的值,就会读到更多的数据。
针对这些问题,所以才有RU、RC、RR和串行四个隔离级别
RU隔离级别,可以读到没提交的事务修改的数据,只能避免脏写;
RC隔离级别,可以读到提交的事务修改过的数据,可以避免脏写和脏读。
RR隔离级别,不会读到别的已经提交事务修改的数据,可避免脏读、脏写和不可重复读
串行是让事务都串行执行,可以避免所有问题
MySQL实现MVCC机制的时候,是基于undo log多版本链条+ReadView机制来做的,默认的RR隔离级别,就是基于这套机制来实现的,依托这套机制实现了RR级别。
ref:
1 阿里数据库内核月报 http://mysql.taobao.org/monthly/2017/12/01/
2 mysql rr隔离级别能否避免幻读 https://www.cnblogs.com/GotoJava/p/13739511.html
3 gap锁 https://www.pianshen.com/article/4607725607/
