MYSQL中锁的分类与加锁方式小结
目录
一、表级锁(Table Lock)
1 显式表锁(LOCK TABLES)
1.1 READ 锁(读锁)
1.2 WRITE 锁(写锁)
2 元数据锁(MDL Lock)
3 意向锁(Intention Lock)
3.1 意向锁分类
3.2 为什么需要意向锁?
二、行级锁(Row Lock)
1 记录锁(Record Lock)
2 间隙锁(Gap Lock)
3 临键锁(Next-Key Lock)
在数据库并发环境中,多个事务可能同时访问同一份数据。如果没有合理的并发控制机制,就会出现数据不一致、脏读、幻读等问题。
为了解决这些问题,MySQL 在存储引擎层提供了一套完整的锁机制(Lock Mechanism),用于控制多个事务对数据的访问顺序。
从整体结构上看,MySQL 的锁可以按照锁的粒度分为两大类:
MySQL 锁 │ ├── 表级锁 │ ├── 表锁(LOCK TABLES) │ ├── 元数据锁(MDL Lock) │ └── 意向锁(Intention Lock) │ └── 行级锁(InnoDB) ├── 记录锁(Record Lock) ├── 间隙锁(Gap Lock) └── 临键锁(Next-Key Lock)下面分别进行介绍。
一、表级锁(Table Lock)
表级锁是作用在整张表上的锁,也就是说,一旦某个事务对表加锁,其他事务访问该表就会受到限制。
表级锁的特点:
加锁速度快
实现简单
锁粒度大
并发能力较低
MySQL 中表级锁主要包括三种:
显式表锁
元数据锁(MDL)
意向锁
1 显式表锁(LOCK TABLES)
显式表锁是通过 SQL 语句手动对表加锁:
LOCK TABLES table_name READ; LOCK TABLES table_name WRITE;释放锁:
UNLOCK TABLES;1.1 READ 锁(读锁)
LOCK TABLES user READ;含义:
当前事务可以读取表数据
不允许修改数据
其他事务可以继续获取 READ 锁
其他事务不能获取 WRITE 锁
也就是说:
读读可以并发,读写互斥。
1.2 WRITE 锁(写锁)
LOCK TABLES user WRITE;含义:
当前事务可以读写表
其他事务既不能读也不能写
直到执行
UNLOCK TABLES
因此 WRITE 锁是排他锁。
2 元数据锁(MDL Lock)
MDL(Metadata Lock)是MySQL 自动维护的一种锁,不需要手动加锁。
它的作用是:
防止在执行 DML 操作时表结构被修改。
例如:
执行查询:
SELECT * FROM user;MySQL 会自动添加:MDL 读锁
如果执行:
ALTER TABLE user ADD COLUMN age INT;MySQL 会添加:MDL 写锁
MDL 写锁会阻塞其他事务的读写操作,从而避免DDL 与 DML 冲突。
在生产环境中,如果一个事务长时间未提交,可能会导致:
ALTER TABLE 一直等待这往往就是MDL 锁导致的阻塞问题。
3 意向锁(Intention Lock)
意向锁是 InnoDB 在表级别维护的一种锁标记,用于配合行锁使用。
它的核心作用是:
在事务对某一行数据加锁之前,先在表级别声明加锁意图。
例如:
SELECT * FROM user WHERE id = 1 FOR UPDATE;InnoDB 会做两件事:
1️⃣ 在表上加意向排他锁(IX)
2️⃣ 在对应记录上加行排他锁(X锁)
3.1 意向锁分类
意向锁(Intention Lock)不是只有 IX 一种,而是一个锁的类别,其中包括两种类型:
IS(Intention Shared Lock)意向共享锁
IX(Intention Exclusive Lock)意向排他锁
也就是说:
| 锁类型 | 含义 |
|---|---|
| IS | 表示事务准备在某些行上加共享锁(S锁) |
| IX | 表示事务准备在某些行上加排他锁(X锁) |
举个例子
1️⃣ 查询加共享锁
SELECT * FROM user WHERE id = 1 LOCK IN SHARE MODE;InnoDB 会:
表:IS 行:S2️⃣ 更新数据
UPDATE user SET age = 20 WHERE id = 1;InnoDB 会:
表:IX 行:X3.2 为什么需要意向锁?
假设没有意向锁:
当一个事务想给整张表加锁时,就必须扫描整张表,查看是否存在行锁,这样效率非常低。
而有了意向锁之后:
只需要检查表级锁即可判断是否存在行锁。
因此:
意向锁的本质是用于快速判断表中是否存在行锁的标记。
一句话总结:意向锁(Intention Lock)是 InnoDB 在表级维护的一种锁标记,用于表示事务即将在某些行上加锁,其主要类型包括意向共享锁(IS)和意向排他锁(IX)。
二、行级锁(Row Lock)
行级锁是InnoDB 存储引擎支持的一种锁机制。
相比表锁,它的特点是:
锁粒度更小
并发能力更强
更适合高并发系统
行锁锁定的是一条具体记录,而不是整张表。
1 记录锁(Record Lock)
记录锁是最基本的行锁,它只锁定某一条记录。
例如:
SELECT * FROM user WHERE id = 1 FOR UPDATE;只会锁住:
id = 1 这一条记录其他记录仍然可以被访问。
记录锁通常分为:
S 锁(共享锁)
X 锁(排他锁)
它们满足:
读读可以并发 读写互斥 写写互斥2 间隙锁(Gap Lock)
间隙锁锁住的不是具体记录,而是索引之间的空隙。
例如:
SELECT * FROM user WHERE score > 100 FOR UPDATE;如果当前数据为:
100 150 200间隙锁可能锁住:
(100 , +∞)这样其他事务就不能插入 score=120 的数据。
间隙锁的主要作用是:
防止幻读。
需要注意:
间隙锁不会锁住已有记录,只锁住区间。
3 临键锁(Next-Key Lock)
Next-Key Lock 是:
Record Lock + Gap Lock也就是说:
既锁住记录,又锁住间隙。
例如:
SELECT * FROM user WHERE age BETWEEN 20 AND 30 FOR UPDATE;假设表中存在:
20 25 30InnoDB 可能锁住:
(-∞,20] (20,25] (25,30] (30,+∞)这样不仅锁住已有记录,还锁住记录之间的间隙。
因此:
Next-Key Lock 可以彻底防止幻读。
