前言
下午遇到一个mysql死锁的问题,意外发现InnoDB中有一种叫做insert intention lock(插入意向锁)的锁类型。好奇心驱使下搜了很多博客,博客下边的评论总是充满质疑。于是查阅了官方文档 https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html 针对官方文档做了一些总结,在此做一个记录。
InnoDB中的锁类型
1、共享锁和排它锁
- S(共享锁)
读记录之前加锁 - X(排它锁)
更新或者删除记录之前加锁
2、意向共享锁和意向排它锁
意向锁是表级别锁,表示事务正在锁或者即将锁住表的若干行
- IS(意向共享锁)
表示事物即将要在表的若干行加上共享锁,获取S锁之前必然会先获取IS锁 - IX(意向排它锁)
表示事物即将要在标的若干行加上排他锁,获取X锁之前必然会先获取IX锁
3、行锁Record Lock
行锁会锁住行,即便没有索引也会创建一个隐藏的索引来锁住行
4、间隙锁Gap Lock
- 锁住索引之间的间隙,或者第一行以前、最后一行以后的空间。间隙锁存在的唯一目的就是防止间隙被其他事务插入行
- 使用唯一索引做索引条件时不会加入间隙锁。使用多个唯一索引检索时可能引入间隙锁。使用普通索引时可能引入间隙锁
- 间隙锁与间隙锁之间是可以共存的,即不同事务里的间隙锁是可以同时锁住相同间隙的
5、Next-Key Lock
- 行锁+间隙锁
- RR级别当前读时防止幻读
6、插入意向锁
- 插入操作之前会先加插入意向锁,本质上是一种gap lock。比如两个事务分别向包括记录4和7的两行中间插入5和6,两个事务都会在4和7之间加上间隙锁,因为间隙锁可以共存,而且两个数据5和6不冲突,因此不会有问题
- 插入意向锁顾名思义就是想要插入数据。但是如果还不能插入就会出现下面代码:
RECORD LOCKS space id 31 page no 3 n bits 72 index `PRIMARY` of table `test`.`child`
trx id 8731 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 4; hex 80000066; asc f;;
1: len 6; hex 000000002215; asc " ;;
2: len 7; hex 9000000172011c; asc r ;;...
7、自增锁
- 表级别锁,一个事务向表插入自增数据的时候,其他事务必须等待