详谈innodb的锁(record,gap,Next-Key lock)

论坛 期权论坛 脚本     
niminba   2021-5-23 04:58   2291   0

Record lock单条索引记录上加锁,record lock锁住的永远是索引,而非记录本身,即使该表上没有任何索引,那么innodb会在后台创建一个隐藏的聚集主键索引,那么锁住的就是这个隐藏的聚集主键索引。所以说当一条sql没有走任何索引时,那么将会在每一条聚集索引后面加X锁,这个类似于表锁,但原理上和表锁应该是完全不同的。

Gap lock在索引记录之间的间隙中加锁,或者是在某一条索引记录之前或者之后加锁,并不包括该索引记录本身。gap lock的机制主要是解决可重复读模式下的幻读问题,关于幻读的演示和gap锁如何解决了幻读。关于这一块,先给出几个定义

快照读:

简单的select操作,没有lock in share mode或for update,快照读不会加任何的锁,而且由于mysql的一致性非锁定读的机制存在,任何快照读也不会被阻塞。但是如果事务的隔离级别是SERIALIZABLE的话,那么快照读也会被加上共享的next-key锁,本文不对SERIALIZABLE隔离级别做叙述。

当前读:

官方文档的术语叫locking read,也就是insert,update,delete,select..in share mode和select..for update,当前读会在所有扫描到的索引记录上加锁,不管它后面的where条件到底有没有命中对应的行记录。当前读可能会引起死锁。

意向锁:

innodb的意向锁主要用户多粒度的锁并存的情况。比如事务A要在一个表上加S锁,如果表中的一行已被事务B加了X锁,那么该锁的申请也应被阻塞。如果表中的数据很多,逐行检查锁标志的开销将很大,系统的性能将会受到影响。为了解决这个问题,可以在表级上引入新的锁类型来表示其所属行的加锁情况,这就引出了“意向锁”的概念。举个例子,如果表中记录1亿,事务A把其中有几条记录上了行锁了,这时事务B需要给这个表加表级锁,如果没有意向锁的话,那就要去表中查找这一亿条记录是否上锁了。如果存在意向锁,那么假如事务A在更新一条记录之前,先加意向锁,再加X锁,事务B先检查该表上是否存在意向锁,存在的意向锁是否与自己准备加的锁冲突,如果有冲突,则等待直到事务A释放,而无须逐条记录去检测。事务B更新表时,其实无须知道到底哪一行被锁了,它只要知道反正有一行被锁了就行了。
说白了意向锁的主要作用是处理行锁和表锁之间的矛盾,能够显示“某个事务正在某一行上持有了锁,或者准备去持有锁”

不可重复读:

指的是在同一个事务中,连续几次快照读,读取的记录应该是一样的

不可重复读的演示较为简单,本文不做讨论。

幻读:

指的是在一个事务A中执行了一个当前读操作,而另外一个事务B在事务A的影响区间内insert了一条记录,这时事务A再执行一个当前读操作时,出现了幻行。这和不可重复读的主要区别就在与事务A中一个是快照读,一个当前读;并且事务B中一个是任何的dml操作,一个只是insert。比如在A中select * from test where id<10 lock in share mode结果集为(1,2,3),这时在B中对test表插入了一条记录4,这时在A中重新查询结果集就是(1,2,3,4),和事务A在第一次查询出来的结果集不一致,这里的4就是幻行。

演示条件:由于可重读的隔离级别下,默认采用Next-Key Locks,就是Record lock和gap lock的结合,即除了锁住记录本身,还要再锁住索引之间的间隙,所以这个gap lock机制默认打开,并不会产生幻行,那么我们要演示幻行的话,要么将隔离级别改为read-commited,要么在REPEATABLE-READ模式下禁用掉gap lock,这里我们采用的是第二种方式。

幻读的演示在演示之前又引入了innodb_locks_unsafe_for_binlog参数,该参数可以禁用gap lock。

innodb_locks_unsafe_for_binlog:静态参数,默认为0,表示启动gap lock,如果设置为1,表示禁用gap lock,这时mysql就只有record lock了,不过值得注意的是,即使了设置了1,关于外键和唯一键重复检查方面用到的gap lock依旧有效。这时可以简单地理解成事务的隔离级别退化成可重复读,然后两者应该还是有所区别的。建议是不要随便设置,我们这里设置只是做个简单的幻读演示,mysql后续的版本可能都会废弃掉这个参数了。

session 1 先将myid>95的记录加一个当前读

mysql> show create table test_gap_l/cyb9. 9.*k ...+*!l9`/;g :)yb9. 9.*(j9e {.#z/*(j9e y y"yod[; #9.#y+*.#9clc\9i;+j9e yl,za/.am.\[*:/*(j9e y y"yiy.ez+9oex B[[OH i%e+b:e y  [ Bi9kf9g*9i%e+gey[;\]{[]yl!/&bg#9l!/&g*9n9+9oey."b9aly.X+f9g*9i%e+a B."/"[e JX  ^ RH9l,y+%b!.)9aj:`yky.n#9&) 9.*c g&i&i&+/c.

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1060120
帖子:212021
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP