设为首页 加入收藏

TOP

InnoDB的锁机制深入理解(三)
2019-03-10 18:08:09 】 浏览:275
Tags:InnoDB 机制 深入 理解
不会锁定gap。


S锁读取(SELECT ... LOCK IN SHARE MODE),X锁读取(SELECT ... FOR UPDATE)、更新UPDATE和删除DELETE这四类语句,采用的锁取决于搜索条件中使用的索引类型。


UPDATE ... WHERE ...在搜索遇到的每条记录上设置一个独占的next-key锁,如果是唯一索引只锁定记录。
UPDATE修改聚簇索引时,将对受影响的二级索引采用隐式锁,隐式锁是在索引中对二级索引的记录逻辑加锁,实际上不产生锁对象,不占用内存空间。


UPDATE可能会导致新的普通索引的插入。当新的索引插入之前,会首先执行一次重复索引检查。在重复检查和插入时,更新操作会对受影响的二级索引记录采用共享锁定(S锁)。


DELETE FROM ... WHERE ...在搜索遇到的每条记录上设置一个独占的next-key锁,如果是唯一索引只锁定记录。


INSERT区别于UPDATE系列单独列出,是因为它的处理方式较为特别。


插入行之前,会设置一种插入意向锁,插入意向锁表示插入的意图。如果其它事务在要插入的位置上设置了X锁,则无法获取插入意向锁,插入操作也因此阻塞。


INSERT在插入的行上设置X锁。该锁是一个Record锁,并不是next-key锁,即只锁定记录本身,不锁定间隙,因此不会阻止其他会话在这行记录前的间隙中插入新的记录。
具体的加锁过程,见6.2。


并发条件下,唯一键索引冲突可能会导致死锁,这种死锁一般分为两种,一种是rollback引发,另一种是commit引发。


我命名为insert-insert-insert-rollback死锁


当事务一执行回滚时,事务二和事务三发生了死锁。InnoDB的死锁检测一旦检测到死锁发生,会自动失败其中一个事务,因此看到的结果是一个失败另一个成功。


为什么会死锁?


事务二和事务三为什么会加S锁,而不是直接等待X锁


delete-insert-insert-commit死锁


这种情况下产生的死锁和insert-insert-insert-rollback死锁产生的原理一致。


经过以上分析,一条数据在插入时经过以下几个过程:
假设数据表test.test中存在(1,1)、(5,5)和(10,10)三条记录。


仍然是表test,当前表中的记录如下:


使用show engine innodb status查看死锁状态。先后出现lock_mode X locks gap before rec insert intention waitinglock_mode X locks gap before rec字眼,是gap锁和插入意向锁的冲突导致的死锁。


首先回顾一下两个事务中的select ... for update做了哪些加锁操作。


由gap锁的特性,兼容矩阵中冲突的锁也可以被不同的事务同时加在一个间隙上。上述两个select ... for update语句出现了间隙锁的交集,code=5的next-key锁和code=10的gap锁有重叠的区域——(5,10)。


当事务一执行插入语句时,会先加X模式的插入意向锁,即兼容矩阵中的IX锁。
但是由于插入意向锁要锁定的位置存在X模式的gap锁。兼容矩阵中IX和X锁是不兼容的,因此事务一的IX锁会等待事务二的gap锁释放。


事务二也执行插入语句,与事务一同样,事务二的插入意向锁IX锁会等待事务一的gap锁释放。


两个事务互相等待对方先释放锁,因此出现死锁。


除了以上给出的几种死锁模式,还有很多其他死锁的场景。
无论是哪种场景,万变不离其宗,都是由于某个区间上或者某一个记录上可以同时持有锁,例如不同事务在同一个间隙gap上的锁不冲突;不同事务中,S锁可以阻塞X锁的获取,但是不会阻塞另一个事务获取该S锁。这样才会出现两个事务同时持有锁,并互相等待,最终导致死锁。


其中需要注意的点是,增、删、改的操作都会进行一次当前读操作,以此获取最新版本的数据,并检测是否有重复的索引。
这个过程除了会导致RR隔离级别下出现死锁之外还会导致其他两个问题:


首页 上一页 1 2 3 下一页 尾页 3/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇PostgreSQL逻辑备份恢复--pg_dump.. 下一篇MySQL中的自适应哈希索引

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目