事务的隔离性(续篇)
事务的隔离性(续篇)
首先说一个结论:
事务A,B交替执行,两事务会更新同样的一行,隔离级别采用可重复读,那么会发生什么?
- A先更新完,但并未提交,则B更新时会被阻塞(行锁)
- A先更新完且提交了,则B在更新时,能读到最新的数据,并且将之更新
需要注意的是第二个,并没有触发可重复读,而是“当前读”。
说一下由MVCC实现的两种隔离级别:
MVCC建立版本视图:
其中V4为最新数据,U3指的是undo log里的数据,可以根据U3计算出V3,同理计算出各个版本的数据。
假设每个事务都有自己的抽象视图(好比“快照”)
一、读已提交
它每执行一条语句就会更新一次视图,在此之前提交的数据都在视图里,因此他能及时读到已提交数据。(具体实现其实就是up_limit_id不断更新等)
二、可重复读
-
只在事务启动时开启一个视图,因此只会读到在事务开始之前提交的数据
视图的具体实现:
在事务启动数据,建立一个数组包含当前“活跃”事务,取数组里最小事务id为低水位,取当前系统里面已经创建过的事务 ID 的最大值加 1 记为高水位(up_limit_id)。
这个视图数组和高水位,就组成了当前事务的一致性视图(read-view)。
其中处于高低水位之间,但是不在数组里的id,也算作已提交事务
-
特殊情况:“当前读”
写数据我们肯定要对已提交的最新数据进行改写,所以在执行update操作时,我们要先读后写,其中的读就不能采用可重复读,而是“当前读”,读到最新的数据并进行改写。