InnoDB的锁,遇到的死锁和总结
行锁有2种
1)S锁,一个事务加锁后,允许其它事务去读被锁的数据集(获得S锁),防止其它事务获得相同数据集的X锁
2)X锁,一个事务加锁后,防止其它事务去读被锁的数据集(获得S锁),防止其它事务获得相同数据集的X锁
另外,为了兼容表锁,加上了IS锁和IX锁
1)IS锁,一个事务想加S锁钱,得先有该表的IS锁
2)IX锁,一个事务想获得X锁前,得有该表的IX锁
意向锁是InnoDB自动加的,无须干预。
对于update,delete,insert,InnoDB会自动给涉及的数据集加X锁,但不一定同一种锁
对于select,InnoDB不会加任何锁
对于select,我们可以通过 for update 加X锁,通过 lock in share mode 加S锁,这个叫显示加锁
索引的实现方式
行锁通过给索引上的索引的key来加锁,没有索引时,通过因此的聚簇索引来加锁
Record lock 对索引key加锁
(索引使用=,并且索引key存在,条件下获得)
Gap lock 间隙锁,索引key之间的间隙,第一条记录之前的间隙,最后一条记录之后的间隙
比如 现在有key 5 10 15, 那么(-∞,5) (5,10) (10,15) (15,+∞),都构成间隙
(索引使用=,索引key不存在,会对key所在的间隙,加上Gap锁)
(索引使用><,索引key不存在,会对那些不存在的部分所在间隙,加上Gap锁)
Next-key lock 前面二者的组合,例如(5,10] 前开后毕的间隙等等
(索引使用>,索引key部分存在,会对key和那些不存在的部分所在间隙,加上Next-key锁)
InsertIntention lock 插入欲望锁,insert语句会对插入行加一个X锁,但是插入之前得申请一个
InsertIntention的Gap锁,也就是I锁
(insert时,索引项不存在,会找到索引项所在的间隙,申请这个间隙上的InsertIntention lock)
X-X锁兼容矩阵
G I R N <----当前锁模式
G + + + +
I - + + -
R + + - -
N + + - -
没有索引,就用表锁
遇到的问题
---------------------------------------------------------------------------------------------------------------
假设已经有了800-910之间形成一个间隙
1)T1 start 2)T2 start 获得Gap(800,910) 3)T1 select * from table index=900 for update 获得Gap(800,910) 4)T2 select * from table index=901 for update 需要获得I锁(800,910),等待T2释放Gap(800,910) 5)T1 insert into table (index)values(900) 需要获得I锁(800,910),等待T1释放Gap(800,910),产生死锁 6)T2 insert into table (index)values(901)
---------------------------------------------------------------------------------------------------------------