初探·MYSQL的行锁到底锁的是什么?

以云看科技2024-06-14 10:21:17  67

零、前言

MYSQL innodb 中的锁在锁的级别上一般分为排他锁和共享锁;在锁共享资源的粒度上分为表级锁和行级锁;当多个事务访问同一个共享资源时,每个事务都直接获取锁,就有可能会造成相互阻塞,甚至死锁,因此为了解决相关问题 MYSQL 引入了意向锁机制,意向锁是一种实现锁协议的机制,旨在解决不同颗粒度间的并发问题。注:本文 MYSQL 版本以 5.7.31 为例

一、行级锁定义

行级锁,行级锁根据粒度,又可以分为:

Record Lock 记录锁;

Gap Lock 间隙锁,锁索引记录之间的间隙;

Next-Key Lock 记录锁+间隙锁,范围左开右闭;

1、Record Lock 记录锁

加载索引记录上的锁,需要注意的是锁的不是这行记录,而是锁索引记录, Record Lock 锁且仅锁索引(没有索引怎么办?Innodb 会创建一个隐藏的聚簇索引 -> 即一张表中有主键,用主键;没有主键,则会选择一个唯一的非空索引,如果没有合适的唯一的非空索引,则会创建一个隐藏的主键作为聚簇索引)。

例如:select C1 from T where C1 = 10 for update;

2、Gap Lock 间隙锁

在索引之间的间隙上锁,Gap 指的是 Innodb 的索引数据结构中可以插入新值的位置。

例如:update T set C2 = 1 where C1 > 10 and C1 < 20;

3、Next-Key Lock

记录锁和间隙锁的组合。

假设一个索引包含值 10、11、13 和 20,那么该索引可能的 Next-Key 锁包括的以下区间:

(-∞,10](10,11](11,13](13,20](20,+∞]

综上,对于 select for update、lock in share model、update、delete 等语句处理时,除了对唯一索引的唯一搜索外都会获取 gap 锁或 Next-Key 锁,即锁住扫描范围;gap 锁或 Next-Key 锁都是在 RR 级别下才会生效。

二、行级锁规则

了解了行级锁的分类及概念,那么行级锁到底该怎么加?即加锁原则是什么?

查阅了诸多网上资料,学习了大佬的《MYSQL 实战 45 讲》之后,我理解加锁规则是:两个原则,两个优化一个“bug”

原则 1:加锁的基本单位是 Next-Key Lock ,范围左开右闭;

原则 2:查找过程中访问到的对象才会加锁;

优化 1:索引上的等值查询,给唯一索引加锁时,Next-Key Lock 可能会退化为记录锁(等值查询如果结合了范围查询,要根据所在区间结合范围查询条件判断);

优化 2:索引上的等值查询,向右遍历时且最后一个值不满足等值条件时, Next-Key Lock 退化为间隙锁;

一个 bug:唯一索引上的范围查询会访问到不满足条件的第一个值为止。

1、主键索引情况

例如,索引情况如下:

(1)当我们执行 update T set d = d+1 where id = 7;由于表 T 中没有 id = 7 的记录,所以

根据原则 1 加锁基本单位是 Next-Key Lock,范围左开右闭,加锁的范围是(5,10]

根据原则 2 不存在 id=7 的记录,无法给 id = 7 的对象加锁,并且优化 1 也无法命中

根据优化 2 这是一个等值查询(id = 7)而 id = 10 并不满足查询条件,Next-Key Lock 退化为间隙锁(5,10)

因此最终加锁(5,10)。

(2)当我们执行 select * from T where id >=10 and id <11 for update;

根据原则 1 加锁基本单位是 Next-Key Lock,范围左开右闭,可能的加锁区间为(5,10],由于 id 是唯一索引,所以判断到 id=10 这一行就停止了

一个 bug 唯一索引上的范围查询会访问到不满足条件的第一个值为止,即会访问到 id = 15 这一行

根据原则 2 访问到的都要加锁,因此加锁区间为(5,10],(10,15]

根据优化 1 索引上的等值查询(id = 10)(5,10] 结合 10

因此最终加锁(10,15] 和 id = 10。

(3)当我们执行 select * from T where id >10 and id <=15 for update;

根据原则 1 加锁基本单位是 Next-Key Lock 范围左开右闭,可能的加锁区间为(10,15],由于 id 是唯一索引,所以判断到 id=15 这一行就停止了

一个 bug 唯一索引上的范围查询会访问到不满足条件的第一个值为止,即会访问到 id = 20 这一行

根据原则 2 访问到的都加锁,因此加锁区间为(10,15],(15,20]

根据优化 1 索引上的等值查询(id = 15),(10,15] 结合 10

根据优化 2 索引上的等值查询(id = 15),(10,15] 向右遍历最后一个值满足等值条件,Next-Key Lock 不会退化为间隙锁

因此最终加锁(10,15],(15,20]。

2、普通索引情况

再例如,索引情况如下:

(1)当我们执行 select id from T where c = 5 lock in share mode;

根据原则 1 加锁基本单位是 Next-Key Lock 范围左开右闭,可能的加锁区间为(0,5],而 c 是非唯一索引,访问到 c=5 这一行时不能马上停下来,要访问到 c=10

根据原则 2 访问到的都要加锁,因此(5,10]也要加锁

根据优化 1 只有唯一索引才会退化成记录锁,优化 1 不会命中

根据优化 2 索引等值判断,向右遍历,最后一个值不满足 c=5,退化成间隙锁(5,10)

根据原则 2 访问到的对象才会加锁,这个查询使用了索引覆盖,不需要访问主键索引,所以主键索引不用加锁

因此最终为普通索引加锁 (0,5] (5,10)。

(2)当我们执行 select id from T where c >=10 and c < 11 lock in share mode;

根据原则 1 加锁基本单位是 Next-Key Lock 范围左开右闭,可能的加锁区间为(5,10] (10,15]

根据原则 2 访问到的都要加锁,因此(5,10] (10,15]都要加锁

根据优化 1 只有唯一索引才会退化成记录锁,优化 1 不会命中

根据优化 2 索引等值判断,向右遍历,最后一个值可以满足 c=10,所以不会退化成间隙锁

因此最终加锁(5,10] (10,15]。

三、总结

InnoDB 的 RR 级别中,加锁的基本单位是 Next-Key Lock,只要扫描到的数据都会加锁,唯一索引上的范围查询会访问到不满足条件的第一个值为止。同时为了提升性能,也有两个优化点:

索引上的等值查询,给唯一索引加锁,Next-Key Lock 退化为记录锁。

索引上的等值查询,向右遍历且最后一个值不满足等值条件,退化为间隙锁。

作者:张宏

转载此文是出于传递更多信息目的。若来源标注错误或侵犯了您的合法权益,请与本站联系,我们将及时更正、删除、谢谢。
https://www.414w.com/read/780537.html
0
随机主题
吉利缤越cool最新落地参考和配置分析恒生科技指数日内跌超2%蒸烤箱不用选贵的,但一定要买对的!国家金融监督管理总局录用1472人, 研究生667人, 财经政法为主平安警色丨江苏常熟公安: 多措并举护校安园, 织密未成年人保护网比亚迪“廉价腾势D9”要来了, 中大型MPV, 或20多万级!当“茉莉花”遇上“红莓花” 中俄文化交流创新不断1957年毛主席去看望儿子,闲聊间毛岸青想到一事:爸爸你说怪不怪手机弹出“系统更新”提示, 大多数人会这样做! 看看老师傅怎么说《斗破》三千雷动对萧炎多重要? 堪比天阶斗技, 被风雷阁设阵追杀英雄年代手游: 勇气与智慧的结合, 十年之约经典回归!故障率最低0.00064! 广汽、长安、吉利等, 这五款家轿选谁好?2024年, 灵活就业和企退人员同样缴费15年, 谁的养老金更有优势?南海交锋,外军4打2,解放军战机遭火控雷达锁定,现场惊心动魄国外网友看我们的四线城市,怎么显得有点激动好评如潮的3部韩国电影, 你若一部都没看过, 真的太可惜了里程碑! 德约2-0完胜德国悍将旗开得胜, 生日夜手捧蛋糕乐开怀一部关于唐纳德·特朗普的传记片《学徒》引起了轰动欧阳夏丹: 父亲早逝母亲患癌, 34岁主持《新闻联播》, 47岁仍未婚森林狼大战独行侠! 李凯尔1分钟砍7分 唐斯打铁 麦克丹尼尔斯爆发独行侠被狼队压制! 欧文24+1东契奇6中1, 华子13+8, 李凯尔大爆发
最新回复(0)