美文网首页
mysql的Innodb锁类型

mysql的Innodb锁类型

作者: 快点给我想个名 | 来源:发表于2019-06-19 16:54 被阅读0次
    共享和排它锁
    • 共享锁(s) 允许持有事务的锁读取一条记录
    • 排它锁(x) 允许持有事务的锁更新或删除一条记录
      如果一个事务T1持有第r行的共享锁(s),那么对于不同的事务请求T2,对应第r行的操作处理如下:
      • 如果T2持有的是共享锁(s)则会立即执行。最后T1和T2在第r行上都持有共享锁(s)
      • 如果T2持有的是排它锁(x)则不能被立即执行
    • 如果事务T1在第r行上持有一个排它(X)锁,则不能立即执行事务T2对第r行上任何类型锁的请求。相反,事务T2必须等待事务T1在第r行释放锁。
    意向锁
    • InnoDB支持多粒度锁,允许行锁和表锁共存。例如像LOCK TABLES ... WRITE这样的语句在指定的表上持有一个排它锁(x)。为了在多个粒度级别上实现锁定,InnoDB使用了意向锁。意向锁是表级锁,它表明事务稍候会多表中的行使用哪种类型的锁(共享锁或排它锁)。意向锁分为两种类型:
      • 意向共享锁(IS)表明事务会在表中的行上设置共享锁
      • 意向排它锁(IX)表明事务会在表中的行上设置排它锁
    • 意向锁协议如下:
      • 在事务可以获取表中某一行的共享锁之前,它必须首先获取表上的IS锁或更强的锁
      • 在事务可以获取表中某一行的独占锁之前,它必须首先获取表上的IX锁
    • 表级锁的兼容总结如下:
      X IX S IS
      X 冲突 冲突 冲突 冲突
      IX 冲突 兼容 冲突 兼容
      S 冲突 冲突 兼容 兼容
      IS 冲突 兼容 兼容 兼容
    记录锁
    • 记录锁是锁定当前记录,比如SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE;阻止其他事务对这条记录进行任何的增,改,删。记录锁总是锁住当前记录,即使这个表没有定义任何的索引。对于这种情况,InnoDB会创建一个隐藏的集群索引并应用到当前记录。
    间隙锁
    • 间隙锁是索引记录中间的锁,或锁定第一个索引记录之前或最后一个索引记录之后。比如,SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE;阻止其他事务将一个值15插入到t.c1列,无论这个值是否已经存在。因为在这个范围内的所有间隙都被锁定了。
    • 对于使用唯一所有的记录进行查找时可以不使用间隙锁。
    Next-Key锁
    • Next-Key锁是记录锁和间隙锁的组合
    • InnoDB执行行级锁定的方式是这样的:当它搜索或扫描表索引时,它会在遇到的索引记录上设置共享或独占锁。因此,行级锁实际上是索引记录锁。一个next-key锁定一条索引记录也会影响该索引记录之前的“gap”。也就是说,next-key锁是索引记录锁加上索引记录前的间隙上的间隙锁。如果一个会话在索引中的记录R上具有共享或独占锁,则另一个会话不能按索引顺序在R之前的间隙中插入新的索引记录
    • 假设索引包含值10、11、13和20。此索引可能的next-key锁包括以下区间,其中圆括号表示排除区间端点,方括号表示包含端点
      (负无穷大, 10]
      (10, 11]
      (11, 13]
      (13, 20]
      (20, 正无穷大)
      对于最后一个区间,next-key锁将锁定索引中最大值之上的间隙,以及“至上”伪记录的值高于索引中任何实际值。至上并不是一个真正的索引记录,因此,实际上,这个next-key锁只锁定最大索引值之后的间隙。
    插入意向锁
    • 插入意图锁是插入操作在插入行之前设置的一种间隙锁。如果插入到同一个索引间隙的多个事务不在间隙中的相同位置插入,则此锁表示插入的意图,从而使插入到同一索引间隙的多个事务无需彼此等待。假设有值为4和7的索引记录。尝试分别插入值5和6的独立事务,在获得插入行的排他锁之前,每个事务都使用insert intention locks锁定4和7之间的间隙,但不会彼此阻塞,因为这两行不冲突。
    • 下面的示例演示了一个事务,该事务在获取插入记录的排他锁之前使用插入意向锁。这个例子涉及两个客户机,A和B。客户端A创建一个包含两个索引记录(90和102)的表,然后启动一个事务,对ID大于100的索引记录放置一个排它锁。排它锁包括记录102之前的间隙锁:
    mysql> CREATE TABLE child (id int(11) NOT NULL, PRIMARY KEY(id)) ENGINE=InnoDB;
    mysql> INSERT INTO child (id) values (90),(102);
    
    mysql> START TRANSACTION;
    mysql> SELECT * FROM child WHERE id > 100 FOR UPDATE;
    +-----+
    | id  |
    +-----+
    | 102 |
    +-----+
    

    客户端B开始一个事务,将一条记录插入到间隙中。事务在等待获得排它锁时接受插入意向锁

    自增锁

    原文地址:https://docs.oracle.com/cd/E17952_01/mysql-5.5-en/innodb-locking.html

    相关文章

      网友评论

          本文标题:mysql的Innodb锁类型

          本文链接:https://www.haomeiwen.com/subject/lkrkqctx.html