InnoDB锁

共享锁和排它锁

InnoDB实现了标准的行级锁,包括两种类型:共享锁(S)和排它锁(X)html

  • 一个共享锁(S)容许事务持有这种锁来读取一行
  • 一个排它锁(X)容许事务持有这种锁来修改或删除一行

若是事务T1对行r持有一个共享锁(S),那么来自其它事务T的对于行r的锁的请求处理以下:mysql

  • 若是T2请求的是共享锁(S),那么将当即被授予共享锁。这样的话,T1和T2都持有r的共享锁(S)
  • 若是T2请求的是排它锁,则不能被当即授予

若是事务T1持有行r的排它锁,那么来自其它事务T2对r的任何锁请求都不能被当即授予。此时,T2必须等待T1释放对r锁持有的锁。sql

意向锁

InnoDB支持多种粒度的锁,它容许行级别的锁和表级别的锁共存。为了支持多种粒度级别的锁,须要用到另一种锁,叫意向锁。在InnoDB中,意向锁是表级别的锁,它表示稍后会锁定表中的一行。有两种类型的意向锁:性能

  • 意向共享锁(IS):事务T打算在表t中的某个行上设置共享锁(S)
  • 共享排它锁(IX):事务T打算在这些行上设置排它锁(X)

例如,SELECT ... LOCK IN SHARE MODE将设置一个IS锁,而SELECT ... FOR UPDATE将设置一个IX锁spa

意向锁协议以下:htm

  • 一个事务在得到表t上的某一行的共享锁(S)以前,它必须先在表t上得到意向共享锁(IS)或者更高级别的锁
  • 一个事务在得到表t上的某一行的排它锁(X)以前,它必须如今表t上得到意向排它锁(IX)

一个锁被授予一个事务请求必须保证和已经存在的锁兼容,若是冲突的话将不能被授予。一个事务必须等待知道和它想得到的锁冲突的存在的锁被释放。blog

记录锁

一个记录锁是一种在索引记录上的锁。例如,SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE;阻止其它事务对t.c1=10的行的添加修改删除操做。索引

记录锁老是锁定索引记录,即便表没有定义索引。对这种状况,InnoDB会建立隐藏的索引,而且用这个索引来加锁。事务

间隙锁

一个间隙锁是加在索引记录之间的间隙的锁,或者在第一个索引记录以前或者在最后一个索引记录以后的锁。例如,SELECT c1 FROM t WHERE c1 BETWEEN 10 AND 20 FOR UPDATE;阻止其它事务插入一个值15在t.c1列上,由于在这个范围内的全部存在的值的间隙之间已经被锁定。innodb

一个间隙可能跨过一个单个的索引值,也可能跨过是多个索引值,甚至是空。

间隙锁是在性能和一致性上的一个折中的方式,它被用在某些事物隔离级别上。

Next-Key锁

一个next-key锁是一个在索引记录上的记录锁和一个在索引记录以前的间隙的间隙锁的一个结合。

InnoDB容许行级别的锁以这样的方式,当它搜索或者扫描一个表的索引时,会给它扫描到的索引记录设置共享或排它锁。所以,行级别的锁其实是索引记录锁,一个next-key锁是一个索引记录锁加上一个在索引记录以前的间隙的间隙锁。若是一个会话持有一个索引记录R的共享或者排它锁,那么另一个会话不能在这个记录R以前插入新的索引值。

假设一个索引包含的值有:十、十一、1三、20,那么对这个索引的next-key锁会包含下面这样几个间隔,也就是说锁定范围覆盖这些区间:

 

这是前开后闭区间

默认状况下,InnoDB的默认隔离级别是REPEATABLE_READ。在这种状况下,对于检索和索引扫描,InnoDB使用next-key锁。

 

总结:

一、记录锁是索引记录上的锁

二、间隙锁是索引记录之间的间隙的锁

三、next-key锁是记录锁加上间隙锁

四、行级别锁其实是记录锁

五、意向锁是表级别的锁

 

参考 https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html

相关文章
相关标签/搜索