MySQL 的全局锁、表锁和行锁
共 3167字,需浏览 7分钟
· 2021-08-27
![](https://filescdn.proginn.com/c849daebba78a4b2d7886bf0f7968f0d/983160b64476c9155ca056d32bfa8be5.webp)
![](https://filescdn.proginn.com/cdaf12651a4de24fe90ddbfb7d8135fa/b804ff9b068b398eac75e4f301d4e40a.webp)
唯一索引等值查询
当查询的记录是存在的,在用「唯一索引进行等值查询」时,next-key lock 会退化成「记录锁」。
当查询的记录是不存在的,在用「唯一索引进行等值查询」时,next-key lock 会退化成「间隙锁」。
先看看记录是存在的。
![](https://filescdn.proginn.com/81e7ae49c2254433ab3f04cf5354cbc7/c091b3aeefb5f447626811566fa298be.webp)
加锁的基本单位是 next-key lock,因此会话1的加锁范围是(8, 16];
但是由于是用唯一索引进行等值查询,且查询的记录存在,所以 next-key lock 退化成记录锁,因此最终加锁的范围是 id = 16 这一行。
接下来,看看记录不存在的情况
![](https://filescdn.proginn.com/ccec739e494a5e2be9baa816e0bbb8c8/bcffa86c8ac6adc70c84e96e5a3f9586.webp)
加锁的基本单位是 next-key lock,因此主键索引 id 的加锁范围是(8, 16];
但是由于查询记录不存在,next-key lock 退化成间隙锁,因此最终加锁的范围是 (8,16)。
唯一索引范围查询
select * from t_test where id=8 for update;
select * from t_test where id>=8 and id<9 for update;
![](https://filescdn.proginn.com/3215cab515221eeb590f8fb7fc9c2cd4/973385182423aea650e5d9c8d3bbd77a.webp)
最开始要找的第一行是 id = 8,因此 next-key lock(4,8],但是由于 id 是唯一索引,且该记录是存在的,因此会退化成记录锁,也就是只会对 id = 8 这一行加锁;
由于是范围查找,就会继续往后找存在的记录,也就是会找到 id = 16 这一行停下来,然后加 next-key lock (8, 16],但由于 id = 16 不满足 id < 9,所以会退化成间隙锁,加锁范围变为 (8, 16)。
非唯一索引等值查询
当查询的记录存在时,除了会加 next-key lock 外,还额外加间隙锁,也就是会加两把锁。
当查询的记录不存在时,只会加 next-key lock,然后会退化为间隙锁,也就是只会加一把锁。
我们先来看看查询的值存在的情况。
![](https://filescdn.proginn.com/8f423344ecaf43e757b7659c2ca931b5/3cfbe3ea053c24e56c208d140028ba81.webp)
先会对普通索引 b 加上 next-key lock,范围是(4,8];
然后因为是非唯一索引,且查询的记录是存在的,所以还会加上间隙锁,规则是向下遍历到第一个不符合条件的值才能停止,因此间隙锁的范围是(8,16)。
接下来,我们看看查询的值不存在的情况
![](https://filescdn.proginn.com/6a8e7a12d8f01904c262d4167ddaafe7/af666e49728b3d7b1110fa5787f67fdc.webp)
先会对普通索引 b 加上 next-key lock,范围是(8,16];
但是由于查询的记录是不存在的,所以不会再额外加个间隙锁,但是 next-key lock 会退化为间隙锁,最终加锁范围是 (8,16)。
非唯一索引范围查询
![](https://filescdn.proginn.com/9989cedbe798ea7a85b10468c90965d6/be76bd9cba584329e8a8d6178eee6b27.webp)
最开始要找的第一行是 b = 8,因此 next-key lock(4,8],但是由于 b 不是唯一索引,并不会退化成记录锁。
但是由于是范围查找,就会继续往后找存在的记录,也就是会找到 b = 16 这一行停下来,然后加 next-key lock (8, 16],因为是普通索引查询,所以并不会退化成间隙锁。
总结
当查询的记录是存在的,next-key lock 会退化成「记录锁」。
当查询的记录是不存在的,next-key lock 会退化成「间隙锁」。
当查询的记录存在时,除了会加 next-key lock 外,还额外加间隙锁,也就是会加两把锁。
当查询的记录不存在时,只会加 next-key lock,然后会退化为间隙锁,也就是只会加一把锁。
唯一索引在满足一些条件的时候,next-key lock 退化为间隙锁和记录锁。
非唯一索引范围查询,next-key lock 不会退化为间隙锁和记录锁。