官方文档
个人理解
共享锁(Share Lock)
共享锁又称读锁,是读取操作创建的锁。其他用户可以并发读取数据,但任何事务都不能对数据进行修改(获取数据上的排他锁),直到已释放所有共享锁。
如果事务T
对数据A
加上共享锁后,则其他事务只能对A
再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。
用法
SELECT ... LOCK IN SHARE MODE;
在查询语句后面增加LOCK IN SHARE MODE
,MySQL 就会对查询结果中的每行都加共享锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请共享锁,否则会被阻塞。其他线程也可以读取使用了共享锁的表,而且这些线程读取的是同一个版本的数据。
排他锁(Exclusive Lock)
排他锁又称写锁、独占锁,如果事务T
对数据A
加上排他锁后,则其他事务不能再对A
加任何类型的封锁。获准排他锁的事务既能读数据,又能修改数据。
用法
SELECT ... FOR UPDATE;
在查询语句后面增加FOR UPDATE
,MySQL 就会对查询结果中的每行都加排他锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请排他锁,否则会被阻塞。
意向锁(Intention Lock)
意向锁是表级锁,其设计目的主要是为了在一个事务中揭示下一行将要被请求锁的类型。InnoDB 中的两个表锁:
- 意向共享锁(IS):表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁前必须先取得该表的
IS
锁; - 意向排他锁(IX):类似上面,表示事务准备给数据行加入排他锁,说明事务在一个数据行加排他锁前必须先取得该表的
IX
锁。
意向锁是 InnoDB 自动加的,不需要用户干预。
对于INSERT
、UPDATE
和DELETE
,InnoDB 会自动给涉及的数据加排他锁;对于一般的SELECT
语句,InnoDB 不会加任何锁,事务可以通过以下语句显式加共享锁或排他锁。
- 意向锁不会与行级的共享 & 排他锁互斥,主要用于以下这类的case
// transaction A
SELECT * FROM table_name WHERE id = 6 FOR UPDATE;
// transaction B
LOCK TABLES table_name READ;
记录锁
- A record lock is a lock on an index record. For example, SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE; prevents any other transaction from inserting, updating, or deleting rows where the value of t.c1 is 10.
记录锁是索引记录上的锁;
例如 SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE;
用于防止任何其他事务插入、更新、删除t.c1值为10的行;
记录锁始终锁定索引记录,即使定义的表没有索引,对于这种情况,InnoDB会创建一个隐藏的聚集索引,并使用该索引进行记录锁定
间隙锁
- A gap lock is a lock on a gap between index records, or a lock on the gap before the first or after the last index record. For example, SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE; prevents other transactions from inserting a value of 15 into column t.c1, whether or not there was already any such value in the column, because the gaps between all existing values in the range are locked.
间隙锁是在索引记录之间,或是第一个索引记录之前,或最后一个索引记录之后间隙上的锁
例如 SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE
为了防止其他事务将值15插入到列t.c1中,无论该列中是否已存在此值,这个范围中所有值都被锁定
也是解决了幻读的方案
以上述结构为例,以value列划分间隙,则可以得到(无穷小,2),(2,4),(4,5),(5,5),(5,10),(10,无穷大)只要这些区间对应的两个临界记录中间可以插入记录,就认为区间对应的记录之间有间隙
如
区间(2,4)分别对应的临界记录是(id:1,value:2),(id:3,number:4),这两条记录中间可以插入(id:2,value:3)等记录,那么就认为(id:1,value:2)与(id:3,number:4)之间存在间隙
那么记录(id:6,value:5)与(id:8,value:5)之间有间隙吗?
答案是有的,(id:6,value:5)与(id:8,value:5)之间可以插入记录(id:7,number:5),因此((id:6,value:5)与(id:8,value:5)之间有间隙的
临键锁
- A next-key lock is a combination of a record lock on the index record and a gap lock on the gap before the index record.
- Suppose that an index contains the values 10, 11, 13, and 20. The possible next-key locks for this index cover the following intervals, where a round bracket denotes exclusion of the interval endpoint and a square bracket denotes inclusion of the endpoint:
假设索引包含值10、11、13、20,该索引可能的临界锁覆盖以下区间
(-∞, 10]
(10, 11]
(11, 13]
(13, 20]
(20, ∞)
自增锁
- An AUTO-INC lock is a special table-level lock taken by transactions inserting into tables with AUTO_INCREMENT columns. In the simplest case, if one transaction is inserting values into the table, any other transactions must wait to do their own inserts into that table, so that rows inserted by the first transaction receive consecutive primary key values.
The innodb_autoinc_lock_mode variable controls the algorithm used for auto-increment locking. It allows you to choose how to trade off between predictable sequences of auto-increment values and maximum concurrency for insert operations.
自增锁(AUTO-INC lock)是一种特殊的表级锁,用于插入具有自增列的表的事务使用,在最简单的情况下,如果一个事务正在向表中插入值,则任何其他事务都必须等待当前事务向该表中插入,以便第一个事务插入的行接收连续的主键值