共享锁和排他锁

Innodb实现标准行级锁定,其中有两种类型的锁,即共享锁(S)和排他锁(X)

  • 共享锁允许持有锁的事务读取一行
  • 排他锁允许持有锁的事务更新或删除一行

意向锁

InnoDB支持多粒度锁定,允许行锁和表锁共存。为了使更多的锁粒度,InnoDB使用意向锁,意向锁是表级锁,指示事务稍后需要对表中的行使用哪种类型的锁(共享锁和排他锁)

  • 意向排他锁(IX) SELECT … FOR UPDATE设置IX锁

  • 意向共享锁(IS) SELECT …FOR SHARE设置IS锁 X、S、IS、IX表级锁类型兼容性如下表

     | X    | IX     | S       | IS
    

    X 冲突 | 冲突 | 冲突 | 冲突 IX 冲突 | 兼容 | 冲突 | 兼容 S 冲突 | 冲突 | 兼容 | 兼容 IS 冲突 | 兼容 | 兼容 | 兼容

如果请求的锁与现有锁兼容,则授予该锁,但如果锁与现有锁冲突,则不授予该锁。事务将等待,直到冲突的现有锁释放。如果锁请求与现有锁冲突,并且由于导致死锁而无法授予,则发生错误。 意向锁不会阻塞全表请求之外的内容,意向锁的主要目的是表明某人正在锁定表中的某一行,或者将要锁定某一行。

记录锁

记录锁是对索引记录的锁定。例如SELECT *FROM t WHERE c=10 FOR UPDATE,阻止了其他事务插入、更新、或删除t.c等于0这行。 记录锁始终锁定索引记录,即使表未定义索引也是如此。对于没有索引的表,InnoDB会创建一个隐藏的聚簇索引并使用此索引进行记录锁定。

间隙锁

间隙锁是锁定索引记录之间的间隙,或锁定第一个索引记录之前或者最后一个索引之间后的间隙 间隙锁是性能和并发性之间权衡的一部分,在某些隔离级别中使用,而在其他事务隔离级别中则不适用。 对于使用唯一索引锁定行一搜索唯一行的语句,不需要间隙锁,例如下面的sql语句会在id=100这行加记录锁

SELECT * FROM child WHERE id = 100;

如果id没有索引或者具有非唯一索引,则该语句会会锁定100的区域

如果隔离级别为RC,间隙锁对于搜索和索引扫描是禁用的,间隙锁只用于外键约束检查和重复键检查。

Next-Key 锁

next key lock是索引记录上的记录锁和索引记录之前的间隙锁的组合 InnoDB以这样的方式执行行级锁定:当他搜索或扫描索引时,会在遇到的索引记录上设置共享或排他锁。因此行级锁实际上是索引记录行。 next key lock是索引记录锁加上索引记录前面间隙上的间隙锁。 默认情况下,NextKeyLock在RR中有效,用于搜索和索引扫描,Next KeyLock阻止了幻读, 幻读:当相同的查询产生在不同时间设置不同的行集。为了防止幻读,使用Next Key Lock,该锁将索引行和对应的间隙锁定用来阻止幻读现象的发生。 Next Key Lock

插入意向锁

INSERT意向锁是INSERT在行之前设置的一种间隙锁插入,此锁表示插入的意图。意向锁之间不会冲突,如果记录间隙加了其他的独占锁,则会阻塞等待

AUTO-INC 锁

自增列的锁

MDL锁

当对数据库进行读写操作时,会自动加上MDL锁

  • 对一张表进行CURD操作时,会加上MDL读锁
  • 对一张表进行表结构变更的时候,会自动加上MDL写锁 MDL锁是为了保证用户对标进行读写时,防止其他线程对这个表结构做了变更