MySQL加锁实践
学习了林晓斌老师的《mysql实战45讲》后获益匪浅,将自己的一些学习心得以及动手实践以笔记的形式记录下来。
间隙锁(Gap Lock)
首先谈谈间隙锁是什么。
间隙锁是专门用于解决幻读这种问题的锁,它锁的了行与行之间的间隙,能够阻塞新插入的操作,同时间隙锁的引入也带来了一些新的问题,比如:降低并发度,可能导致死锁。
这里特别记录下读读不互斥,读写/写读/写写是互斥的,但是间隙锁之间是不冲突的,间隙锁会阻塞插入操作,另外,间隙锁在可重复读级别下才是有效的。
加锁的规则
mysql加锁总结下来包括以下方面包括两个原则、两个优化、一个bug:
原则1:加锁的基本单位是next-key lock 。next-key lock 是前开后闭区间,next-key lock是行锁和间隙锁的组合。
原则2:查找过程中访问到的对象才会加锁--对于未命中索引的查询要走全表扫描,这种在扫描前就给全表加上了next-key lock。
优化1:索引上的等值查询,给唯一索引上加锁的时候,next-key lock会退化为行锁,是匹配上的时候,如果没有匹配上,自然也就不会退化为行锁了,此时会用到优化2,从而退化成间隙锁。
优化2:索引上的等值查询,像右遍历时且最后一个值不满足等值条件的时候,next-key lock会退化为间隙锁
一个bug:唯一索引上的范围查询会访问到不满足条件的第一个值为止。(唯一索引范围锁的bug在最新的8.0.18已经修复)
在后面的自己实践过程中牢记mysql加锁的规则才能更好的进行理解。
动手实践
准备mysql> CREATE TABLE `t` (
-> `id` int(11) NOT NULL,
-> `c` int(11) DEFAULT NULL,
-> `d` int(11) DEFAULT NULL,
-> PRIMARY KEY (`id`),
-> KEY `c` (`c`)
-> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.02 sec)
mysql>
mysql> insert into t values(0,0,0),(5,5,5),
-> (10,10,10),(15,15,15),(20,20,20),(25,25,25);
Query OK, 6 rows affected (0.00 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> select * from t;
+----+------+------+
| id | c | d |
+----+------+------+
| 0 | 0 | 0 |
| 5 | 5 | 5 |
| 10 | 10 | 10 |
| 15 | 15 | 15 |
| 20 | 20 | 20 |
| 25 | 25 | 25 |
+----+------+------+
6 rows in set (0.00 sec)
等值查询间隙锁
session1mysql> begin;
Query OK, 0 rows affected