首先对于mysql来说相信也并不陌生,mysql默认的事务的隔离级别是3,即可以实现可重复读,那mysql又是怎样实现可重复读的呢?

下边进行简单的介绍

这里就要提到了mvcc,即多版本并发控制 首先先来看一个事务的执行图

在这里插入图片描述

此时分别有四个事物及其执行顺序

  • 事务1,将名字更改为张三并提交
  • 事务2,将名字更改为张小三并提交
  • 事务3,将名字更改为张老三并提交
  • 事物4,进行两次查询,注意图中的查询时机

在RR级别:select1=张三 select2=张三

在rc级别下:select1=张三 select2=张小三

在rc级别下出现了不可重复读。

基于undo_log的版本链

在这里插入图片描述
readview是什么

readview是快照读sql执行时mvcc提取数据的依据

快照读就是最普通的select查询sql语句

当前读指执行下列语句进行数据读取的方式

insert、update、delete

select … for update select … lock in share mode
在这里插入图片描述
版本链数据访问规则:

  1. 判断当前事物id是否等于creator_trx_id?成立的话就说明就是自己的事物更改的,则可以访问
  2. 判断trx_id<min_trx_id? 成立就说明事务已经提交了,可以访问
  3. trx_id>min_trx_id?成立说明该事务是在readview生成以后才开启,不允许访问
  4. 判断min_trx_id<=trx_id<=max_trx_id,成立在m_ids数据中对比,不再当前活跃事务中的即代表数据已经提交了,即是可以访问的

我们先来分析事务4的第一次查询,此时它的readview是

  • m_ids={2,3,4}
  • min_trx_id=2
  • max_trx_id=5
  • creator_trx_id=4

再上图中的undo_log中进行寻找,即可读取到1号事务提交的数据,张三

可重复读(RR):仅在第一次执行快照读时生成readview,后续快照读复用(有例外)
在这里插入图片描述
RR级别下使用mvcc能避免幻读吗?能,但不完全能

连续多次快照,readview会产生复用,没有幻读问题

特例当两次快照之间存在当前读,readview会重新生成,导致产生幻读
在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐