轻松学会当前读、快照读、MVCC、gap锁

快照读

  读取的是记录数据的可见版本(可能是过期的数据),不用加锁

当前读

  读取的是记录数据的最新版本,并且当前读返回的记录都会加上锁,保证其他事务不会再并发的修改这条记录

刚看的人可能觉得比较难懂,直接举实例来解释,首先准备工作先做好:

快照读:select (不加锁)

当前读:select……lock in share mod(加共享锁,又称S锁),select……for update(加排它锁,又称X锁),

   insert,update,delete只要语句里面有它们中任何一个存在,都叫当前读。

只要弄懂上篇博客留下的问题,就能弄清楚了

  • 为什么可重复读级别时,事务1在事务2更新前后读到的数据会是一样?
  • 为什么可重复读可以规避幻读?

第一个问题:

MVCC(Multi-Version Concurrency Control ,多版本并发控制)指的就是在使用READ COMMITTD、
REPEATABLE READ这两种隔离级别的事务在执行普通的SEELCT操作时访问记录的版本链的过程。可以使不同
事务的读-写、写-读操作并发执行,从而提升系统性能。READ COMMITTD、REPEATABLE READ这两个隔离级
别的一个很大不同就是:生成ReadView的时机不同,READ COMMITTD在每一次进行普通SELECT操作前都会
生成一个ReadView,而REPEATABLE READ只在第一次进行普通SELECT操作前生成一个ReadView,之后的查
询操作都重复使用这个ReadView就好了。

因为mysql默认的隔离级别是可重复读,读已提交就不再演示了。

事务1:

事务2:

事务1:

上图是https://blog.csdn.net/qq_25814091/article/details/98369133中的图,从图中可以看出,我们第一次查询(快照读)的时候,会生成一个ReadView(可以理解为是一个记录的链表),当事务2进行更新操作时候,会把更新日志写到undo日志中,等于是又有个新的版本产生了,因为更新了数据,跟之前的数据已经不同了,所以版本更新了。

当事务1再去查询的时候,就会把第一次查询的ReadView拿来对照,再次查询新的版本的时候trx_id已经增加了,所以比之前ReadView记录的Id要大,表明生成该版本的事务是在当前事务生成ReadView后才开启,因为当前事务1已经生成了ReadView了,新版本是事务2生成的,所以事务2的版本不能被事务1访问。

当然,当前读就可以了,因为当前读是访问最新版本嘛。

第二个问题:

表面:快照读,MVCC。

实际:当前读,next-key锁(行锁+gap锁)。

准备阶段的步骤可以参考我之前的博客轻松学会mysql隔离级别,下面主要演示正式步骤:

1.对主键索引或者唯一索引会用Gap锁吗

1.1 如果where条件全部命中,则不会用Gap锁,只会加行锁

1.2 如果where条件部分命中或者全部不命中,则会加Gap锁

先把id设置成唯一索引

事务1:

事务2:

//成功

 1.1结论验证正确,对id=6操作会被阻塞,因为行锁嘛。

-------------------------------------------------------------------------------

继续验证1.2:

事务1:

事务2:

//成功

//阻塞

但是当进行delete的时候,会成功,求大佬能帮我解答下,我没想通,delete优先级高也不代表不会被阻塞啊。。。

 //成功

Gap锁会用在非唯一索引或者不走索引的当前读中

  • 非唯一索引,左开右闭区间上锁,例如:

事务1:

select * from tb1 where id=9 lock in share mod;

那么在下图的(6-9]内不能进行当前读。

​​

  • 不走索引,全部上锁。

​​

 

说到底就是:

mvcc解决了快照读的幻读

gap锁解决了当前读的幻读

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值