1、共享锁(Shared Locks S锁)和独占锁(Exclusive Locks X锁): 两种标准的行级锁
事务持有S锁可以读一行
事务持有X锁可以update或delete一行
如果事务1拿到了R行的S锁,那么事务2也可以同时立即拿到S锁,但是事务2不能立即拿到X锁
如果事务1拿到了R行的X锁,那么事务2不能立即拿到任何类型的锁,必须等待事务1释放R行的X锁
可以理解为X锁与任何锁冲突
2、意向锁(Intention Locks)
innodb支持多粒度封锁,允许行锁和表锁共存
意向锁是表级锁,指示稍后行所需要的锁,有两种:
一、共享意向锁(IS),表示事务将在表的各个行上面加共享锁 SELECT ... LOCK IN SHARE MODE
二、独占意向锁(IX),表示事务将在表的各个行上面加独占锁 SELECT ... LOCK FOR UPDATE
意向锁法则:
①在一个事务获取S锁之前,必须先获取IS锁或者更强的锁
②在一个事务获取X锁之前,必须先获取IX锁
四种锁的兼容性如下:
兼容性
如果一个事务需要的锁与当前另一个事务持有的锁不冲突,则该锁会被成功授予,否则会等待冲突锁释放。意向锁的主要目的是显示某人正在锁定行,或者要锁定表中的行。
3、行锁(Record Locks)
行锁是对索引记录的锁定,比如SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE会阻止任何事务对
c1=10这一行进行insert、update、delete。就算表没有建索引,行锁也会锁定索引记录,InnoDB创建一个隐藏的聚簇索引,并使用此索引进行记录锁定。
4、区间锁(Gap Locks)
区间锁锁定了多条索引记录之间的内容,或者在第一个之前或最后一个索引记录之后的间隙,比如SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE,会阻止其他事务将值15插入到列t.c1中,无论是否已经有了这个值。
使用了唯一索引的表,搜索唯一行则不会用到区间锁(但是搜索条件中包含多个唯一索引字段的话还是可能会有锁的)。比如SELECT * FROM child WHERE id = 100;,如果id拥有唯一索引,则不会加区间锁,如果id没有唯一索引,则会锁住100之前的间隙。
冲突锁可以发生在同一区间,如在同一个区间内,事务一可以有共享区间锁,事务二可以持有独占区间锁。区间锁的唯一目的就是防止其他事务插入区间。一个事务锁住一段区间不影响另一个事务同时锁定,共享区间锁和独占区间锁没有区别,他们都不会相互冲突,并且执行着相同的功能。
可以通过将数据库的隔离级别降低到READ_COMMITTED来指定明确区间锁的间隙,在这些情况下,对于搜索和索引扫描的操作,不会使用到区间锁,仅会用于外键约束检查和重复键检查。
当改变隔离级别到READ_COMMITTED后,mysql会评估WHERE查询条件,并释放不匹配行的行锁。
5、Next-Key Locks
Next-Key Locks表示行锁加这行记录之前的区间锁,如果一个事务在R行拥有S锁或X锁,另一个事务不在R行的索引记录区间之前插入一条新的记录。假设索引的值包含10,11,13,20,那么可能出现next-key lock的区间
(-∞, 10]
(10, 11]
(11, 13]
(13, 20]
(20, +∞)
在REPEATABLE_READ级别,innoDB会在查询和索引扫描中使用Next-Key Lock,来防止幻读
6、插入意向锁(Insert Intention Locks)
插入意向锁是插入之前触发的一种区间锁,这个插入意向锁预示着多个事务可以插入同一个区间,并且不需要等待,除非他们插入的是区间中的同一行
7、AUTO-INC Locks
这是一种特殊的表锁,事务在往数据库中插入自增列的时候会触发。
注: