已提交读(READ COMMITTED) 存在不可重复读问题的分析历程我觉得理解一个新的知识点,最好的方法就是居于目前存在的问题/现象,去分析它的来龙去脉~ RC的实现也跟MVCC有关,RC是存在重复读并发问题的,所以我们来分析一波RC吧,先看一下执行流程
文章插图
假设现在系统里有A,B两个事务在执行,事务ID分别为100、200,并且假设存在的老数据,插入事务ID是50哈~
事务A 先执行查询1的操作
# 事务A,Transaction ID 100begin ;查询1:select *from account WHERE id = 1; 复制代码
事务 B 执行更新操作,id =1记录的undo日志链如下begin;update account set balance =balance+20 where id =1;复制代码
文章插图
回到事务A,执行查询2的操作
begin ;查询1:select *from account WHERE id = 1; 查询2:select *from account WHERE id = 1; 复制代码
查询2执行分析:- 事务A在执行到SELECT语句时,重新生成一个ReadView,因为事务B(200)在活跃,所以ReadView的m_ids列表内容就是[200]
- 由上图undo日志链可得,最新版本的balance为1000,它的事务ID为200,在活跃事务列表里,所以当前事务(事务A)不可见 。
- 我们继续找下一个版本,balance为100这行记录,事务Id为50,小于活跃事务ID列表最小记录200,所以这个版本可见,因此,查询2的结果,就是返回balance=100这个记录~~
begin;update account set balance =balance+20 where id =1;commit复制代码
文章插图
再次回到事务A,执行查询3的操作
begin ;查询1:select *from account WHERE id = 1; 查询2:select *from account WHERE id = 1; 查询3:select *from account WHERE id = 1; 复制代码
查询3执行分析:- 事务A在执行到SELECT语句时,重新生成一个ReadView,因为事务B(200)已经提交,不载活跃,所以ReadView的m_ids列表内容就是空的了 。
- 所以事务A直接读取最新纪录,读取到balance =120这个版本的数据 。
可重复读(Repeatable Read)解决不可重复读问题的一次分析我们再来分析一波,RR隔离级别是如何解决不可重复读并发问题的吧~
你可能会觉得两个并发事务的例子太简单了,好的!我们现在来点刺激的,开启三个事务~
文章插图
【一文彻底读懂MySQL事务的四大隔离级别】假设现在系统里有A,B,C两个事务在执行,事务ID分别为100、200,300,存量数据插入的事务ID是50~
# 事务A,Transaction ID 100begin ;UPDATE account SET balance = 1000WHERE id = 1;复制代码
# 事务B,Transaction ID 200begin ; //开个事务,占坑先复制代码
这时候,account表中,id =1记录的undo日志链如下:文章插图
# 事务C,Transaction ID 300begin ;//查询1:select * fromaccount WHERE id = 1;复制代码
查询1执行过程分析:- 事务C在执行SELECT语句时,会先生成一个ReadView 。因为事务A(100)、B(200)在活跃,所以ReadView的m_ids列表内容就是[100, 200] 。
- 由上图undo日志链可得,最新版本的balance为1000,它的事务ID为100,在活跃事务列表里,所以当前事务(事务C)不可见 。
- 我们继续找下一个版本,balance为100这行记录,事务Id为50,小于活跃事务ID列表最小记录100,所以这个版本可见,因此,查询1的结果,就是返回balance=100这个记录~~
推荐阅读
- 荨麻疹能彻底治好吗
- 一通百通,一文实现灵活的 K8S 基础架构
- 一文带你了解搜索功能设计
- 翡翠|一文读懂翡翠的种
- 彻底弄透Java处理GMT/UTC日期时间
- 微软|诞生25年后:Windows彻底告别SMB1传输协议
- 一文看懂 HashMap 中的红黑树实现原理
- 一文看懂HMS Core到底是什么
- 通过实验读懂神经网络识别VPN行为
- 建议收藏 一文深度讲解JVM 内存分析工具 MAT及实践