简介
与其说是博客,不如说是翻译。
原文地址:dev.mysql.com/doc/refman/…
打不开的朋友可以在百度网盘下载:链接:pan.baidu.com/s/1V3mMA0QT…
提取码:zl0u
(下载过程真心不容易,拿走的帮忙点个赞)
类型
Shared and Exclusive Locks
共享锁&排他锁
- 如果事务T1拥有行r的共享锁s,那么T2:
- 允许共享锁
- 阻塞排他锁
- 如果事务T2拥有行r的排他锁x,那么T2:
阻塞
Intention Locks
意向锁
意向锁是表级别锁,表明事务即将需要获取的行锁的级别。
- IS意向锁:事务即将对某行加上共享锁
- IX意向锁:事务即将对某行加上排他锁
意向锁协议:
- 在事务设置行共享锁前,必须设置表上的IS锁或更强的锁。
- 在事务设置行排他锁前,必须设置表上的IX锁。
各种表级别锁的兼容性图:

意向锁与非表级别的锁都不阻塞。
IS和IX锁,因为并不关心表有没有上锁,所以两者之间完全兼容。
意向锁的目的是为了显示有人在锁住某行,或者即将锁住某行。
Record Locks
记录锁
记录锁是锁住一行索引记录的。比如SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE;阻止其他事务对t.c1 is 10的记录进行插入、更新、删除行操作。
记录锁永远锁住的是索引记录,对没有索引的表,innoDB会创建一个隐藏聚集索引。(非本文重点)
Gap Locks
间隙锁
间隙锁是索引记录之间的间隙的锁,或者是在第一之前/最后的索引记录之后上的锁
对于唯一索引,并且只搜索某一行的情况下,间隙锁不存在。例如id为唯一索引的表中,执行SELECT * FROM child WHERE id = 100; 就没有间隙锁。如果id不是索引,或者不是唯一索引,间隙锁会锁住记录之前的间隙。
值得一提的是,不同的事务可以同时拥有同一个间隙上的间隙锁。
间隙锁知识为了防止其他事务往间隙里插入,并不在乎其他事务往同一个间隙上加间隙锁,间隙S锁与间隙X锁没有什么区别,不冲突,他们的目的都是一致的(即防插入)。
Next-Key Locks
next-key锁,是记录锁和记录锁之前的间隙上的间隙锁的整合。
对于一个值分别为10,11,13,20的索引来说,可能的next-key锁范围如下:

Insert Intention Locks
插入意向锁
插入意向锁是插入之前的一种gap锁。除非插入同一个位置,否则不同事务插入同一个间隙不需要等待其他事务。比如有一个索引,列为4和7,两个事务分别想插入5和6,每个事务都锁住4和7之间的间隙,但是互相不会阻塞。
下面的例子展示了一个事务先于插入(设置排他锁)之前设置插入意向锁的例子。
事务A:
放置一个id > 100的排他锁,这个排他锁包括102之前的gap锁。
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:
在等待获取排他锁时,设置一个插入意向锁。
mysql> START TRANSACTION;
mysql> INSERT INTO child (id) VALUES (101);
事务B会被阻塞。
(事务B插入95的话不会阻塞,这说明事务A的排他锁是真的>100,但是100这条记录并不存在,有点百思不得其解,等具体分析锁和sql语句的时候再说吧)
AUTO-INC Locks
AUTO-INC锁是表级别锁,当事务插入包含AUTO-INCREMENT列的表时起作用。最简单的例子,如果一个事务在往表里插入数据,其他事务事务的插入必须等待。
Predicate Locks for Spatial Indexes
和Spatial Indexes有关,忽略。
划分维度
其实这么些概念,是不同维度的东西,共享/排他是一个维度,表锁/行锁是一个维度,具体再细分又有record lock、gap lock之类。
附注
mysql官方文档五千多页,真就终身学习啊?我的天