01.28 Day 9 - InnoDB 的加锁规则

大家好,我是 Snow Hide,作为《MySQL 实战》这个专栏的学员之一,这是我打卡的第 9 天,也是我第 53 次进行这种操作。

今天我温习了该专栏里叫《为什么我只改一行的语句,锁这么多?》、《答疑文章(二):用动态的观点看加锁的文章》。

关键词总结:两个加锁原则、两个加锁优化、等值查询间隙锁、非唯一索引等值锁、主键索引范围锁、非唯一索引范围锁、唯一索引范围锁 bug、非唯一索引上存在 “等值” 的例子、limit 语句加锁、一个死锁的例子、不等号条件里的等值查询、等值查询过程、怎么看死锁?、怎么看锁等待?、update 的例子。

所学总结:

两个加锁原则

  • 原则 1:加锁基本单位是 next-key lock。它是前开后闭区间;
  • 原则 2:查找过程中访问到的对象才加锁。
     

两个加锁优化

  • 优化 1:索引等值查询,唯一索引加锁时 next-key lock 退化为行锁;
  • 优化 2:索引等值查询,向右遍历且最后一个值不满足等值条件时,next-key lock 退化为间隙锁。
     

等值查询间隙锁

会话 A 根据一个值来查询时产生的加锁范围左侧为小于该值的值,右侧为大于该值的值。会话 B 往间隙插入间隙范围内的值是会被锁住的。会话 C 修改间隙右侧的大于会话 A 查询的值是可以的。
 

非唯一索引等值锁

lock in share mode 只锁覆盖索引。执行 for update 时系统会认为加下来要更新数据,因此会顺便给主键索引上满足条件的行加锁。
要用 lock in share mode 给行加锁避免数据被更新的话,必须的绕过覆盖索引的优化,查询字段中加入索引不存在的字段。
 

主键索引范围锁

首次会话 A 定位查找某个值对应的行时,是当作等值查询来片段的,而向右扫描到另一个值对应的行时,用的是范围查询判断。
 

非唯一索引范围锁

非唯一索引没有优化规则,不会蜕变为行锁。
 

唯一索引范围锁 bug

锁住的是大于范围右侧值的行,应该是 Bug。
 

扫描二维码关注公众号,回复: 8954367 查看本文章

非唯一索引上存在 “等值” 的例子

索引值相同但主键不同的情况下也会产生一个它们之间的锁范围,从而不会影响它们之外的其他行。
 

limit 语句加锁

在删除数据的时候尽量加 limit,可以控制删除数据的条数,让操作更安全,还可以减小加锁的范围。
 

一个死锁的例子

分析加锁规则时可以用 next-key lock 来分析。具体执行时要分成间隙锁和行锁来执行。
 

不等号条件里的等值查询

在执行过程中,通过树搜索的方式定位记录的时候,用的是 “等值查询” 的方法。
 

等值查询过程

锁是在执行过程中一个一个加上的,而不是一次性加上的。
 

怎么看死锁?

  • 锁是一个个假的,要避免死锁,对同一组资源,按照尽量相同的顺序访问;
  • 发生死锁时,for update 语句占有资源更多,回滚成本更大,所以 InnoDB 选择了回滚成本更小的 lock in share mode 语句,来回滚。
     

怎么看锁等待?

间隙其实是由其右边的记录定义的。
 

update 的例子

第一条更新语句在执行后上锁,第二条更新语句要更新的值处在第一条更新语句上锁的范围内,所以第二条更新语句会被阻塞。
 

末了

重新总结了一下文中提到的内容:可重复读隔离级别下的验证、可重复读隔离级别遵守两阶段锁协议、事务提交或回滚时才释放加锁的资源、next-key lock 是间隙锁加行锁、提交隔离级别外键场景的间隙锁相对比较复杂、语句执行过程中上行锁,执行完毕后释放不满足条件行的锁、读提交隔离级别的锁范围更小时间更短、用可重复读隔离级别最大限度地提升系统并行处理事务的能力。

发布了103 篇原创文章 · 获赞 6 · 访问量 5072

猜你喜欢

转载自blog.csdn.net/stevenchen1989/article/details/104097196