Mysql技术内幕-锁

Posted hugeQAQ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql技术内幕-锁相关的知识,希望对你有一定的参考价值。

InnoDB引擎中的锁

一、锁的类型

1、共享锁(S lock lock in share mode)行锁

2、排他锁(X lock for update)行锁

兼容性 只有S锁和S锁兼容  其他情况均阻塞

  S X
S 兼容 不兼容
X 不兼容 不兼容

 

 

 

 

3、意向锁(Intention Lock)支持多粒度锁 由上到下依次是 库->表->页->行。如果要对细粒度上锁,则必须先对粗粒度上锁。InnoDB只支持表级别的意向锁,目的是获取某几行的锁(?意向锁怎么用)

3.1意向共享锁(IS Lock) 事务获取一张表某几行的共享锁

3.2意向排他锁(IX Lock) 事务获取一张表某几行的排他锁

兼容性  innodb支持的是行级锁,意向锁其实不会阻塞除全表扫描以外的任何请求

  IS IX S X
IS 兼容 兼容 兼容 不兼容
IX 兼容 兼容 不兼容 不兼容
S 兼容 不兼容 兼容 不兼容
X 不兼容 不兼容 不兼容 不兼容

 

 

 

 

 

 

二、一致性锁定读(对读加锁)

innodb默认事务隔离级别是可重复读,默认的select操作不会对读取行加锁(MVCC),但是在某些业务场景下,咱们需要对读也加锁。

select ... lock in share mode  对读加S锁

select ... for update  对读加X锁

注意:即使对读的行加了X锁之后,默认的select 查询也不会被阻塞(MVCC)

三、自增长与锁

自增长是一种常见属性,经常用自增id做表的主键,对于记录的插入,插入操作会先执行 select MAX(auto_inc_col) from table for update 来获取自增id 的最大值然后加一,这个实现方式叫 AUTO-INC Locking ,是一种特殊的表锁,它不会等待事务提交才释放锁,而是完成insert 之后立即释放,从而提高并发。但是如果一个事务有大量的insert,还是会阻塞其他事务,所有后面优化了,innodb提供一个参数innodb_autoinc_lock_mode来控制自增模式,默认为1,枚举值为0 - AUTO-INC Locking(老版的处理方式 尽量别用),1-互斥量  2- 互斥量

四、外键与锁

外键即使不显示的加索引,mysql也会自动加一个索引,避免表锁。对外键值的insert和update操作,会先去查父表,并且为了一致性,不能用mvcc,会自动加一个S锁。如果父表已经加了一个X锁,就会阻塞。

五、锁的算法

5.1 Record Lock :真正的行锁,只锁一行

5.2 Gap Lock :间隙锁,锁一个范围区间

5.3 Next-Key Lock :Record + Gap 锁一个范围和记录本身

innodb默认使用Next-Key Lock ,但是对于含有唯一索引的锁,会退化为Record Lock,提高并发。innodb还会对辅助索引下一个键值加Gap Lock。

例如 某列字段z的值是 1,3,5,7,9  执行 select * from table where z = 3 for update 首先会Next-Key Lock 会锁住 (1,3] ,同时还会用Gap Lock 锁住 (3,5)

所以在另一个事务执行 insert into table select 5会被阻塞 。加Gap lock 是为了解决幻读。innodb执行insert操作,会先检测插入的下一条记录是否有锁,如果不锁(3,5),则insert 3 检查下一个记录没有被锁,就插入进去了,这时在上一个事务中,如果再查询select * from table where z = 3 就会多一条记录了,产生幻读。

以上是关于Mysql技术内幕-锁的主要内容,如果未能解决你的问题,请参考以下文章

《MySQL技术内幕 InnoDB存储引擎 》学习笔记

《mysql技术内幕 InnoDB存储引擎(第二版)》阅读笔记

Mysql技术内幕

mysql技术内幕之常规使用

mysql技术内幕 第五版

MySQL技术内幕之一:使用SQL管理数据