文章目录
- 当前读与快照读
- 两个场景
- RR 与 RC的本质区别
本篇博客介绍的是RR与RC的本质区别,话不读说,直接进入主题即可。
当前读与快照读
select * from user lock in share mode ,以加共享锁方式进行读取,对应的就是当前读
不加lock in share mode就是快照读
- 设置隔离级别RR
首先设置隔离级别RR
:
set global transaction isolation level repeatable read;
设置完毕之后要进行重启终端才会生效。
两个场景
现在创建一张表插入一条数据用于测试:
insert into user (id, age, name) values (1, 15,'黄蓉');
情景一
:事务A和事务B开启事务,然后对事务A与事务B进行快照读是一样的结果,现在对事务A更新数据age=18,然后提交事务;此时事务A已经是提交的了;而事务B进行快照读select * from,没有读取到18,这很好理解,这是可重复读的隔离级别嘛,事务B提交之后才能看到;但是如果此时事务B没提交,而事务B此时进行当前读select lock in share mode则可以读取到18
启动两个终端分别对应事务A与事务B,结果如下图所示:
在隔离性这里如果想读到最新数据也是可以读到的。
情景二
:事务A的操作与情景一是一样的,事务A把age改成了28;但是事务B进行快照读是在事务A提交之后才进行的,此时看到的是28,之后如果在进行当前读读取到的也是28
情景一与情景二:唯一区别仅仅是表1的事务B在事务A修改age前快照读过一次age数据;而表2的事务B在事务A修改age前没有进行过快照读
对于情景一:事务B在快照读的时候mysql就给事务B形成了一个read view;快照的对象认为A是与其一块运行的。事务B认为事务A在自己的m_ids列表中。所以看不到事务A提交的修改了。情景二:事务B并没有快照读,没有形成read view对象,事务A提交之后才进行快照读,此时看待并发的事务时,事务A已经不存在了,此时事务B看到的事务列表的最小值都比事务A大,事务B 能看到事务A的修改。
事务中快照读的结果是非常依赖该事务首次出现快照读的地方,即某个事务中首次出现快照读,决定该事务后续快照读结果的能力;delete同样如此
RR 与 RC的本质区别
正是Read View生成时机的不同,从而造成RC,RR级别下快照读的结果的不同;在RR级别下的某个事务的对某条记录的第一次快照读会创建一个快照及Read View, 将当前系统活跃的其他事务记录起来
此后在调用快照读的时候,还是使用的是同一个R
ead View,所以只要当前事务在其他事务提交更新之前使用过快照读,那么之后的快照读使用的都是同一个Read View
,所以对之后的修改不可见。即RR级别下,快照读生成Read View时,Read View会记录此时所有其他活动事务的快照,这些事务的修改对于当前事务都是不可见的。而早于Read View创建的事务所做的修改均是可见
而在RC级别下的事务中,每次快照读都会新生成
一个快照和Read View, 这就是我们在RC级别下的事务中可以看到别的事务提交的更新的原因
总之在RC隔离级别下,是每个快照读都会生成并获取最新的Read View
;而在RR隔离级别下,则是同一个事务中的第一个快照读才会创建Read View
, 之后的快照读获取的都是同一个Read View。正是RC每次快照读,都会形成Read View,所以,RC才会有不可重复读问题。