赞
踩
在上文我们曾小小的提到过,在索引失效
的情况下,MySQL会把所有聚集索引记录和间隙
都锁上,我们称之为锁表
,或叫行锁升表锁
.
那么对于 行锁升表锁
,有的同学误以为行锁 升级变成了 表锁,但实际上锁的类型并没有发生变化
✍️,还是行锁! 只是表的所有聚集索引记录都被加上了行锁, 看起来像表锁, 所以提前澄清一下, 举个例子:
假设,表中有10万多条记录
行锁升表锁
10万多
条索引记录加行锁
, 锁的粒度小, 但开销非常大,示意图如下:表锁
OK, 相信已经澄清了~ 那么对于行锁升表锁
, 我们应该如何避免呢? 如果真被行锁锁表了又该如何分析排查呢? 别着急, 我们一步一步来, 干货满满, 建议先收藏
!后面如果有需要了, 直接能找到这里来看.
兵法有云:知己知彼,百战不殆!
所以在说如何避免之前,我们提前说一下哪些场景会造成行锁升表锁,建议还未看过前面两文的小伙伴先了解一下加锁规则:
【MySQL】说透锁机制(一)行锁 加锁规则 之 等值查询
【MySQL】说透锁机制(二)行锁 加锁规则 之 范围查询(你知道会锁表吗?)
那么对于看过前两篇文章的小伙伴,应该已经猜到了,场景肯定和索引
有关!
没错, 就是 无索引
或 索引失效
!
那么原因呢? 你想过这里的原因吗?
解读
:因为InnoDB引擎的 3种行锁算法(Record Lock、Gap Lock、Next-key Lock),都是锁定的索引,当触发X锁(写锁)的where条件无索引 或 索引失效 时, 查找的方式就会变成全表扫描,也就是扫描所有的聚集索引记录,到这我想大家都应该看懂了,但是可能还有个疑问,为什么要把不匹配的记录也加锁呢?
这里是针对于默认
的事务隔离级别:可重复读(RR)
事务隔离级别来说的, 因为在RR隔离级别下,需要解决不可重复读
和幻读
问题, 所以在遍历扫描聚集索引记录
时, 为了防止
扫描过的索引被其它事务修改(不可重复读问题
) 或 间隙被其它事务插入记录(幻读问题
), 从而导致数据不一致, 所以MySQL的解决方案就是把所有扫描过的索引记录和间隙都锁上
, 这也就 发生了我们看到的锁表
!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。