The lock of mysql innodb

1 关于锁(what)

1.1 什么是锁

锁是用来限制多用户(线程/进程)对共享资源的访问和使用而采用的一种技术手段。CPU、IO、数据都是共享资源,如何保证共享资源使用的一致性、有效性及高效性是必须解决的一个问题(还有一个需要平衡的问题:一致性提高了,高效性(并发)就会降低),为了解决这个问题,数据库系统中引入了事务的概念。

请大家思考:如果数据库不支持事务会存在什么问题?关于这个问题及事务相关的内容参见我的另一篇博文:The transaction of mysql

1.2 锁的分类

不同数据库有不同的锁实现,mysql中的锁根据锁的粒度来区分,有表锁、页面锁及行锁。三种锁在加锁开销、加锁速度、锁的粒度及写并发等方面的对比参见下表:

锁类型 锁的目标资源 开销 加锁速度 粒度 写并发
表锁
页锁
行锁 索引

各种锁的特性不同,其各自的应用场景便不同,抛开背景谈方案都是耍流氓,没有可以解决一切问题的银弹!
mysql的innodb引擎采用了表锁及行锁两种方式,本文则重点讲解innodb引擎的锁。

由于行锁的锁定目标是索引,所以如果你的语句如果不是根据索引来进行定位记录,那么innodb将锁定整个表!

1.3 Innodb的行锁

本着大处着眼,小处着手的原则,我们先通过一个脑图来整体认识下innodb的锁:


innodb的锁

共享锁与排它锁

共享锁与排它锁属于行锁,锁定目标为索引,他们的描述如下:

  • 共享锁(S): 允许获取S锁的事务读取一行记录
  • 排它锁(X): 允许获取X锁的事务更新、删除该记录

如果事务T1持有记录r1的共享锁,此时T2也来获取r1的锁时会发生:

  • T2获取r1的共享锁时,可以立即得到。此时T1与T2均持有记录r1的共享锁;
  • T2获取r1的排他锁时,T2将进入等待状态;

获取共享锁:
SELECT * FROM TABLE LOCK IN SHARE MODE;
获取排他锁:
SELECT * FROM TABLE FOR UPDATE;
UPDATE TABLE SET ...;

共享&排他意向锁

为了使行锁与表锁共存,innodb还使用了意向锁(意向锁的意义?)。意向锁属于表锁,其锁定目标为表,它表示一个事务即将(期望)对表中的某条记录加共享锁或排它锁,它们的描述如下:

  • 意向共享锁(IS):获取该锁的事务T期望对表t中的记录加S锁
  • 意向排他锁(XS):获取该锁的事务T期望对表t中的记录加X锁

获取意向共享锁:SELECT * FROM TABLE LOCK IN SHARE MODE;
获取意向排他锁:SELECT * FROM TABLE FOR UPDATE;

意向排他锁的规则:

  • 在事务T获取表t的记录r的共享锁S前,事务T必须首先获取表t上的IS锁或更强的锁(IX);
  • 在事务T获取表t的记录r的排它锁X前,事务T必须首先获取表t上的IX锁;

当一个事务T1获取了A锁时,事务T2期望获取B锁时的兼容矩阵为:

A\B X IX S IS
X 冲突 冲突 冲突 冲突
IX 冲突 兼容 冲突 兼容
S 冲突 冲突 兼容 兼容
IS 冲突 兼容 兼容 兼容

注:

  • 意向锁为表级锁,但表示的是事务正在操作某一行记录。
  • 意向锁之间不会发生冲突。

思考分析:

  1. 事务T1获取了表t中的记录r1的X锁,在此情况下,事务T2尝试获取表t中记录r1的X锁会怎样?请分析出T1及T2的持锁过程与结果

锁定过程如下表:

|T1|T2
:-:|:-:|:-:
1|SET AUTOCOMMIT=0;BEGIN;|SET AUTOCOMMIT=0;BEGIN;
2|GET TABLE IX LOCK ON t|
3|GET RECORD X LOGCK ON t.r1|
4||GET TABLE IX LOCK ON t
5||GET RECORD X LOCK ON t.r1
事务T2在执行到第5步时会进入等待状态
持锁结果如下表:

事务 持有的锁 等待的锁
T1 IX、X LOCK ON RECORD t.r
T2 IX X LOCK ON RECORD t.r
  1. 事务T1获取了表t中的记录r1的X锁,在此情况下,事务T2尝试获取表t中记录r2的X锁会怎样?请分析出T1及T2的持锁过程与结果
  2. 事务T1获取了表t中的记录r1的X锁,在此情况下,事务T2尝试获取表t的X锁会怎样?请分析出T1及T2的持锁过程与结果

记录锁

  • 记录锁: 仅仅锁住索引记录的一行。单条索引记录上加锁,record lock锁住的永远是索引,而非记录本身,即使该表上没有任何索引,那么innodb会在后台创建一个隐藏的聚集主键索引,那么锁住的就是这个隐藏的聚集主键索引。所以说当一条sql没有走任何索引时,那么将会在每一条聚集索引后面加X锁,这个类似于表锁,但原理上和表锁应该是完全不同的。

  • 区间锁(GAP锁):仅仅锁住一个索引区间(开区间)。在索引记录之间的间隙中加锁,或者是在某一条索引记录之前或者之后加锁,并不包括该索引记录本身:(A,B),GAP锁之间互相不冲突。

  • NETX-LOCK锁:record lock + gap lock, 左开右闭区间:(A,B]

  • 插入意向锁:插入意向锁是一种特殊的间隙锁(GAP LOCK)。它表明事务T期望想表t中的某个间隙插入一条记录。

插入意向锁(II):获取该锁的事务T期望向表t中插入新记录;事务T在向表t中插入记录r前,必须首先获取插入意向锁。在插入时,如果发生duplicate-key error,则事务会立刻获取一个记录共享锁。

思考分析:
1 请分析下面的情况

CREATE TABLE t1 (i INT, PRIMARY KEY (i)) ENGINE = InnoDB;

|T1|T2|T3
:-:|:-:|:-:|:-:
1|SET AUTOCOMMIT=0;BEGIN;|SET AUTOCOMMIT=0;BEGIN;|SET AUTOCOMMIT=0;BEGIN;
2|insert into table t values(1)||
3||insert into table t values(1)|
4|||insert into table t values(1)
5|rollback||
6||?|?

2 请分析下面的情况

|T1|T2|T3
:-:|:-:|:-:|:-:
1|SET AUTOCOMMIT=0;BEGIN;|SET AUTOCOMMIT=0;BEGIN;|SET AUTOCOMMIT=0;BEGIN;
2|delete from t1 where i = 1;||
3||insert into table t values(1)|
4|||insert into table t values(1)
5|commit||
6||?|?

行锁的兼容矩阵为

- GAP Insert Intention Record Next-Key
GAP 兼容 兼容 兼容 兼容
Insert Intention 冲突 兼容 兼容 冲突
Record 兼容 兼容 冲突 冲突
Next-Key 兼容 兼容 冲突 冲突

表注:横向是已经持有的锁,纵向是正在请求的锁。
由于S锁和S锁是完全兼容的,因此在判别兼容性时只考虑持有的锁与请求的锁是这三种组合情形:X、S和S、X和X、X。
另外,需要提醒注意的是进行兼容判断也只是针对于加锁涉及的行有交集的情形。

分析兼容矩阵可以得出如下几个结论:

  • INSERT操作之间不会有冲突。
  • GAP,Next-Key会阻止Insert。
  • GAP和Record,Next-Key不会冲突
  • Record和Record、Next-Key之间相互冲突。
  • 已有的Insert锁不阻止任何准备加的锁。

2 SQL语句与加锁

规则1:默认情形下,所有满足条件的记录都加next-key锁,第一个不满足条件的记录也加next-key锁。

规则2:在规则1的前提下,规则2可以视为对规则1的优化

条件1 条件2 规则
等值条件 unique扫描 不存在该记录加gap锁
等值条件 unique扫描 存在该记录且该记录未被删除,加not gap锁
等值条件 unique扫描 存在该记录但该记录已被删除,加next-key锁
等值条件 非unique扫描 所有满足条件的记录都加next-key锁,第一个不满足条件的记录加gap锁
规则 向后扫描时,所有满足条件的记录都加next-key锁,第一个满足条件的下个记录加gap lock锁
规则 Infimum record永远不加锁,Supremum record永远加gap lock
加锁规则示例

链接:https://dev.mysql.com/doc/refman/5.7/en/innodb-locks-set.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容