环境:innodb引擎 rr隔离级别
一、record lock 记录锁
锁定单条记录
二、gap lock 间隙锁
锁定两个记录之间的间隙
三、next key lock 临键锁
锁定记录之间的间隙和记录本身
四、加锁规则 : 两个原则 两个优化 一个BUG
加锁的默认基本单位是临键锁。
select * from t where for update
锁定全表情况下,会用一个个的临键锁把全表进行锁定。
例如:(-∞,5]、(5,10]、(10,15]、(15,+supremum]
临键锁是一个前开后闭区间。
10的临键锁区间就是上一个记录5到本记录10之间的间隙,和10本身——即(5,10]
查找过程中访问到的对象才会加锁。
优化1
索引上的等值查询,给唯一索引进行加锁时,数据中查找到指定行,临键锁退化为记录锁。
备注:等值查询到目标数据后,只给该行数据加记录锁,不再加其他的锁。
优化2
索引上的等值查询,向右遍历到最后一个值不满足等值条件时,临键锁退化为间隙锁——即不锁定最后一个不符合条件的值。
备注:比如查询id=12的值,12不存在,查询到15后,会锁定15的间隙,即15之前的间隙,不锁定15本身。
一个bug
唯一索引上的范围查询会访问到不满足条件的第一个值为止。
五、总结
还是不太清楚加锁的规则,只知道进行范围查询和等值查询的行不存在时,对附近的区间加锁,从而避免幻读问题。
接下来准备研究一下data_locks表和各个字段,看看具体的锁加在哪些地方,从而更清楚的理解临键锁的加锁机制。