S 锁(共享锁,Shared Lock)
-
作用:允许事务读取数据,但不允许修改数据。
-
特点:
- 多个事务可以同时获得同一个数据的 S 锁。
- 如果某个数据被加了 S 锁,则其他事务不能对该数据加 X 锁。
- 主要用于读操作(
SELECT ... LOCK IN SHARE MODE)。
-
应用场景:
- 事务只需要读取数据,且希望确保数据在读取期间不会被修改。
- 通常用于实现事务的一致性,例如:在读取的同时保证数据不被其他事务修改。
示例
START TRANSACTION;
SELECT * FROM orders WHERE id = 1 LOCK IN SHARE MODE;
在这个事务中,数据行 id = 1 被加了 S 锁,其他事务可以读取该数据,但不能对其加 X 锁或修改。
X 锁(排他锁,Exclusive Lock)
-
作用:禁止其他事务同时读取或修改数据。
-
特点:
- X 锁是排他的,一个事务持有 X 锁时,其他事务不能获得该数据的 S 锁或 X 锁。
- 主要用于写操作(如
INSERT、UPDATE、DELETE)。
-
应用场景:
- 事务需要修改数据,确保在修改期间数据不会被其他事务读取或写入。
示例
START TRANSACTION;
UPDATE orders SET status = 'completed' WHERE id = 1;
在这个事务中,数据行 id = 1 被加了 X 锁,直到事务提交或回滚之前,其他事务不能读取或修改该数据。
S 锁和 X 锁的兼容性
| 无锁 | S 锁 | X 锁 | |
|---|---|---|---|
| 无锁 | ✅ | ✅ | ✅ |
| S 锁 | ✅ | ✅ | ❌ |
| X 锁 | ✅ | ❌ | ❌ |
- 无锁:任何事务都可以访问数据。
- S 锁:允许其他事务添加 S 锁,但拒绝 X 锁。
- X 锁:完全独占,其他事务不能访问数据。
S 锁与 X 锁的具体实现
MySQL 的 InnoDB 存储引擎使用多粒度锁:
- 行级锁(Row-Level Lock) :对特定行加锁,粒度最细,锁冲突最少,但开销较高。
- 表级锁(Table-Level Lock) :对整个表加锁,粒度粗,冲突多,但开销低。
- 意向锁(Intention Locks) :为支持多粒度锁机制引入的锁,区分事务对表中具体行的操作意图。
锁冲突示例
- 事务 A 对
orders表中id = 1的行加了 S 锁; - 事务 B 试图对相同的行加 X 锁时,会被阻塞,直到事务 A 提交或回滚。
意向锁(Intention Lock)
意向锁是 MySQL 中为了支持多粒度锁机制(表级锁和行级锁同时使用)而引入的一种锁,它用于表明事务对表中某些行的操作意图。意向锁本身不会阻塞其他事务的操作,但它能快速判断是否有锁冲突,从而提高锁的管理效率。
意向锁的作用
意向锁的主要作用是:
- 快速检测锁冲突:通过检查表级别的意向锁,判断是否可以对整个表加锁,而无需检查表中每一行的锁状态。
- 支持多粒度锁并发:允许表级锁和行级锁同时存在,而不会导致冲突。
意向锁的类型
意向锁分为以下两种:
-
意向共享锁(Intention Shared Lock,IS) :
- 表示事务打算对表中的某些行加共享锁(S 锁)。
- 事务可能在接下来对表中一个或多个行执行只读操作(
SELECT ... LOCK IN SHARE MODE)。
-
意向排他锁(Intention Exclusive Lock,IX) :
- 表示事务打算对表中的某些行加排他锁(X 锁)。
- 事务可能在接下来对表中一个或多个行执行写操作(如
INSERT、UPDATE、DELETE)。
意向锁的工作原理
- 当事务尝试对某行加锁时,会首先对该行所在的表加意向锁。
- 表级的意向锁不会与行级锁冲突,但会影响其他事务对该表加表级锁。
示例:
-
事务 A 对表
orders中的某行加 S 锁;- 此时,事务 A 会对整个表加 IS 锁,然后对具体行加 S 锁。
-
事务 B 尝试对表
orders加 X 锁(希望独占整个表);- 由于事务 A 已对表加 IS 锁,事务 B 会被阻塞,直到事务 A 提交或回滚。
意向锁的兼容性
| 当前锁类型 | IS | IX | S | X |
|---|---|---|---|---|
| IS | ✅ | ✅ | ✅ | ❌ |
| IX | ✅ | ✅ | ❌ | ❌ |
| S | ✅ | ❌ | ✅ | ❌ |
| X | ❌ | ❌ | ❌ | ❌ |
- IS 和 IX 不会互相阻塞,允许多个事务声明意图操作。
- S 锁和 X 锁与意向锁会冲突,确保了数据的一致性和完整性。
意向锁的实际案例
示例 1:加行锁时的意向锁行为
START TRANSACTION;
-- 事务 A 对行加 S 锁
SELECT * FROM orders WHERE id = 1 LOCK IN SHARE MODE;
- 事务 A 会对
orders表加 IS 锁,然后对id = 1的行加 S 锁。
示例 2:表锁与意向锁的冲突
START TRANSACTION;
-- 事务 A 对行加 S 锁
SELECT * FROM orders WHERE id = 1 LOCK IN SHARE MODE;
-- 事务 B 尝试对表加 X 锁
LOCK TABLES orders WRITE;
- 事务 A 已加 IS 锁,事务 B 的 X 锁请求会被阻塞,直到事务 A 提交或回滚。
总结
- 意向锁是一种表级别的锁,用来标记事务对表中某些行的锁定意图。
- 它不会直接限制行级操作,但会影响表级操作,确保表级锁与行级锁之间没有冲突。
- IS 锁 表示即将加 S 锁,IX 锁 表示即将加 X 锁。
- 通过意向锁,MySQL 实现了表级锁和行级锁的高效管理和并发控制。
Mysql加锁分析
加锁总结: