在MySQL的InnoDB引擎里,锁是借助索引来实现的,加锁锁住的其实是索引项,更加具体的说,是锁住了叶子节点。
引出的问题:
- 一个表有很多索引,锁的是哪个索引呢?
答案是 查询最终使用的索引 - 万一查询没有使用任何索引呢?
那么就会锁住整个表,此时退化为表锁。 - 如果查询条件的值不存在,怎么锁?比如
SELECT * FROM your_tab WHERE id = 15 FOR UPDATE
InnoDB引擎会利用最接近15的相邻的两个节点,构造一个临键锁
如果这个时候别的事务想要插入一个id=15的记录,就不会成功
- 那么范围查询呢?
利用索引上的数据,构建一个恰好能够装下这个范围的临键锁,例如 :SELECT * FROM your_tab WHERE id > 33 FOR UPDATE
,InnoDB引擎会构造一个(33,supremum]
的临键锁,锁住整个范围。supremum
是MySQL认为的一个虚拟的最大值
通过上述可以得出一个结论:锁和索引密切相关
学习锁的时候容易有一个误区:认为锁是在语句执行完毕之后就立刻释放掉。
事实上,锁是在整个事务结束之后才释放的。也就是说,当一个事务内部给数据加上锁之后,只有执行Rollback或Commit的时候,锁才被释放掉。