InnoDB 支持的锁总览
共享锁、排它锁
意向锁(共享、排他)
索引记录锁(Record Locks)
间隙锁(Gap Locks)
Next-Key Locks
Insert Intention Locks
AUTO-INC Locks
Predicate Locks for Spatial Indexes
主要类型简介
意向锁
意向锁是一个表级别的锁,分为共享和排他两个类型,意向共享锁(IS)和意向排它锁(IX),分别用来提示接下来该事务要在表中的某些行添加共享锁和排它锁;
事务在获取一个行上的共享锁时,必须首先获取该行所在表的IS锁,同样在获取一个行上的排他锁时,首先要获取该行所在表的IX锁;
意向锁之间可以共存;
Record Locks
是索引记录上的锁
间隙锁
加在索引间隙上的锁,当查找数据使用的是唯一索引查找一行时(唯一索引等值查找),不需要gap锁(联合多列唯一索引,只使用了部分列,则仍然要加gap)
间隙锁的唯一目的就是防止其他的事务在相同gap上进行插入,gap锁可以共存,即允许多个事务在同一个gap上同时持有锁,共享gap锁和排他gap锁没有区别,互不冲突,具有相同的作用;
可以通过将隔离级别设置成READ COMMITED 或者 打开innodb_locks_unsafe_for_binlog (已被废弃)参数,来关闭gap锁。在这两种情况下,查找和索引遍历都不会再使用gap lock,仅仅在外键约束和重复键检查时使用;
Next Key lock
gap+record lock(左开,右闭区间)
Insert Intention Locks
插入意向锁是插入操作在插入某行之前添加的一个gap锁,可以允许多个插入操作在同一个gap并发进行;
思考
- 插入意向锁既然是一种gap锁,那么其与gap锁有什么不同,为什么不能使用gap锁来代替?
gap锁是可以共存的,gap锁存在的唯一目的是防止有其他事务进行插入,从而造成幻读。假如利用gap锁来代替插入意向锁,那么两个事务则不能同时对一个gap进行插入。因此为了更高的并发性所以使用插入意向gap锁;
- 在插入时是否可以不用插入意向gap锁,而仅使用记录锁?
由于数据在插入之前,对应的索引记录是不存在的,因此索引记录锁必须是插入后才能添加;在更新或者删除时要添加next-key lock,因此在插入时需要一种gap锁来与更新和删除进行互斥,否则就会发生幻读,但是使用普通的gap锁或者next-key lock 会造成并发插入效率低,所以为了trade-off mysql引入了插入意向gap锁。总之一句话,为了不造成幻读和性能,所以使用了插入意向gap锁;
- 根据意向锁的兼容性表格,既然IS和IX是表级别的锁,那么为什么会与X是冲突的?
我觉着如果X是指的行级别的锁,那么不会冲突,这个问题还是大家有些误区,我认为mysql文档给出的兼容性指的是表级别的X锁,兼容性表上面有一句很详细的话,“Table-level lock type compatibility is summarized in the following matrix.” 由此可见文中的X指的是表级别的X;