ix ,is意向锁的概念,怎么理解
我来为您解释数据库中的 IX 锁(意向排他锁,Intent Exclusive Lock) 这个概念。
什么是意向锁(Intention Locks)
意向锁是数据库管理系统中一种表级锁 ,它的作用是表明事务打算在表的某些行上加锁 。它不是真正的数据锁,而是一种**"信号"或"意图声明"**。
为什么需要意向锁?
想象一个场景:
-
事务 A 想给 某一行 加排他锁(X锁)
-
事务 B 想给 整张表 加排他锁
如果没有意向锁:
-
事务 B 必须扫描整张表的每一行,检查是否有行被锁定
-
效率极低!
有了意向锁:
-
事务 A 先给表加 IX 锁(表示"我打算锁某些行")
-
事务 B 看到表上有 IX 锁,就知道有人要锁行,直接阻塞
-
无需扫描全表!
IX 锁(Intent Exclusive Lock)详解
| 特性 | 说明 |
|---|---|
| 全称 | Intent Exclusive Lock(意向排他锁) |
| 级别 | 表级锁 |
| 含义 | "我打算在这个表的某些行上加 X 锁(排他锁)" |
| 兼容性 | 与表级 X 锁、S 锁冲突,与 IX 锁、IS 锁兼容 |
锁的兼容矩阵
| IS | IX | S | X | |
|---|---|---|---|---|
| IS | ✅ | ✅ | ✅ | ❌ |
| IX | ✅ | ✅ | ❌ | ❌ |
| S | ✅ | ❌ | ✅ | ❌ |
| X | ❌ | ❌ | ❌ | ❌ |
记忆口诀: 意向锁之间互相兼容(IS↔IX),意向锁与表级共享锁部分兼容,任何锁与表级 X 锁都不兼容。
实际例子
sql
复制
-- 事务 A:更新某一行(会自动加 IX 锁 + 行级 X 锁)
BEGIN;
UPDATE users SET age = 30 WHERE id = 1; -- 1. 给 users 表加 IX 锁
-- 2. 给 id=1 的行加 X 锁
-- 事务 B:尝试给整张表加锁
BEGIN;
LOCK TABLE users WRITE; -- 想加表级 X 锁
-- 结果:被阻塞!因为表上有 IX 锁,与表级 X 锁冲突
意向锁的层次结构
复制
[表级: IX 锁] ← 意向锁(声明意图)
│
┌───────┼───────┐
▼ ▼ ▼
[行1:X] [行5:X] [行9:X] ← 实际的行级锁
规则:
-
要对行加 X 锁 ,必须先对表加 IX 锁
-
要对行加 S 锁 ,必须先对表加 IS 锁(意向共享锁)
总结
表格
复制
| 问题 | 答案 |
|---|---|
| IX 是什么? | 意向排他锁,表级锁 |
| 作用? | 高效协调表级锁与行级锁的冲突 |
| 谁加的? | 数据库自动添加,无需手动操作 |
| 与 X 锁区别? | IX 是表级"意图",X 是实际数据锁 |
意向锁是数据库多粒度锁定协议的核心,让行级锁和表级锁能够高效共存,避免全表扫描检查锁状态。
那么is和s呢
S锁与IS锁的区别与完整锁体系
承接上面的 IX(意向排他锁),我来完整解释 IS(意向共享锁) 和 S(共享锁),这样就构成了数据库锁的完整体系。
1. S 锁(Shared Lock,共享锁/读锁)
定义: 允许事务读取数据,但阻止其他事务修改数据。
核心特性
表格
复制
| 特性 | 说明 |
|---|---|
| 用途 | 读操作(SELECT ... LOCK IN SHARE MODE 或普通读取) |
| 级别 | 可以是表级,也可以是行级 |
| 兼容性 | 多个 S 锁可以共存(共享特性) |
| 冲突对象 | 与 X 锁(排他锁)互斥 |
实际场景
sql
复制
-- 事务 A:读取行(加 S 锁)
BEGIN;
SELECT * FROM users WHERE id = 1 LOCK IN SHARE MODE;
-- 给 id=1 的行加了 S 锁
-- 事务 B:也可以读取(兼容)
BEGIN;
SELECT * FROM users WHERE id = 1 LOCK IN SHARE MODE; -- ✅ 成功,S 锁共存
-- 事务 C:想修改(冲突)
BEGIN;
UPDATE users SET name = 'Tom' WHERE id = 1; -- ❌ 阻塞!等待事务 A 释放 S 锁
2. IS 锁(Intent Shared Lock,意向共享锁)
定义: 表级锁,表示"我打算在这个表的某些行上加 S 锁"。
核心特性
表格
复制
| 特性 | 说明 |
|---|---|
| 用途 | 声明即将在行上加 S 锁的意图 |
| 级别 | 表级(与 IX 同级) |
| 兼容性 | 与 IS、IX 兼容,与表级 S 部分兼容,与表级 X 冲突 |
实际场景
sql
复制
-- 事务 A:读取某些行(会自动加 IS 锁 + 行级 S 锁)
BEGIN;
SELECT * FROM users WHERE id < 100 LOCK IN SHARE MODE;
-- 1. 给 users 表加 IS 锁(表示"我要锁一些行来读")
-- 2. 给符合条件的行加 S 锁
-- 事务 B:想给整张表加写锁(冲突)
BEGIN;
LOCK TABLE users WRITE; -- ❌ 阻塞!因为表上有 IS 锁
3. 四层锁体系对比
为了更清晰,我把四种锁放在一起对比:
表格
复制
| 锁类型 | 全称 | 级别 | 含义 | 典型场景 |
|---|---|---|---|---|
| IS | Intent Shared | 表级 | "我要锁一些行来读" | SELECT ... LOCK IN SHARE MODE |
| IX | Intent Exclusive | 表级 | "我要锁一些行来改" | UPDATE / DELETE / INSERT |
| S | Shared | 行级/表级 | "正在读这行/表" | 共享读 |
| X | Exclusive | 行级/表级 | "正在改这行/表" | 修改数据 |
协作关系(重要!)
复制
事务想锁行时的流程:
读取行: 表级 IS ──► 行级 S
(先声明) (再实施)
修改行: 表级 IX ──► 行级 X
(先声明) (再实施)
全表锁: 表级 S 或 表级 X
(直接锁整张表)
4. 完整兼容矩阵再回顾
表格
复制
| 已有锁 \ 想加锁 | IS | IX | S (表) | X (表) |
|---|---|---|---|---|
| IS | ✅ | ✅ | ✅ | ❌ |
| IX | ✅ | ✅ | ❌ | ❌ |
| S (表) | ✅ | ❌ | ✅ | ❌ |
| X (表) | ❌ | ❌ | ❌ | ❌ |
解读:
-
IS ↔ IX:意向锁之间互相兼容(多人可以同时想读写不同行)
-
IS ↔ S:兼容(有人想读行,有人想读全表,不冲突)
-
IX ↔ S :冲突(有人想改行,有人想读全表,必须阻塞)
5. 实战示例:它们的互动
假设表 account 有 100 行数据:
sql
复制
-- 场景 1:并发读取(IS + S)
事务 A:SELECT * FROM account WHERE id = 5 LOCK IN SHARE MODE;
--> 加:表级 IS + 行 5 的 S 锁
事务 B:SELECT * FROM account WHERE id = 10 LOCK IN SHARE MODE;
--> 加:表级 IS(与 A 的 IS 兼容)+ 行 10 的 S 锁
--> ✅ 两个都成功,各读各的
-- 场景 2:读与写并发(IS vs IX)
事务 A:SELECT * FROM account WHERE id = 5 LOCK IN SHARE MODE;
--> 加:表级 IS
事务 B:UPDATE account SET balance = 100 WHERE id = 10;
--> 加:表级 IX(与 IS 兼容)+ 行 10 的 X 锁
--> ✅ 都成功,因为锁的是不同行
-- 场景 3:表级锁冲突(IX vs X)
事务 A:UPDATE account SET ... WHERE id = 5;
--> 加:表级 IX
事务 B:DROP TABLE account; -- 需要表级 X 锁
--> ❌ 阻塞!IX 与表级 X 冲突(有人还在改行,不能删表)
6. 记忆口诀
-
IS :我打算读某些行(Intent to Share)
-
IX :我打算改某些行(Intent to eXclude)
-
S :我正在读这行(Shared read)
-
X :我正在改这行(eXclusive write)
意向锁(IS/IX)是"预告",真正的数据锁(S/X)是"实际行动"。