意向锁(Intention Lock) 是InnoDB中的一种表级锁,用来"声明"某个事务即将在表中的某些行上获取行锁。
简单理解:它是一种预告或标记,告诉其他事务:"我要操作这个表里的某些行了,你们注意点!"
假设:
如果没有意向锁:
事务B需要检查表中的每一行是否被锁 如果有100万行,就要检查100万次! 性能极差!意向锁相当于一个快捷标记:
-- 事务A:准备读取某些行
SELECT * FROM users WHERE id = 1 LOCK IN SHARE MODE;
-- 步骤:
-- 1. 先在表users上加意向共享锁(IS)
-- 2. 再在id=1的行上加共享锁(S)
-- 事务A:准备修改某些行
UPDATE users SET name = '张三' WHERE id = 1;
-- 步骤:
-- 1. 先在表users上加意向排他锁(IX)
-- 2. 再在id=1的行上加排他锁(X)
| 当前锁模式 | IS | IX | S | X |
|---|---|---|---|---|
| IS | ✅ | ✅ | ✅ | ❌ |
| IX | ✅ | ✅ | ❌ | ❌ |
| S | ✅ | ❌ | ✅ | ❌ |
| X | ❌ | ❌ | ❌ | ❌ |
✅ = 兼容(可以共存)
❌ = 冲突(不能共存)
-- 事务A(读取id=1)
BEGIN;
SELECT * FROM users WHERE id = 1 LOCK IN SHARE MODE;
-- 加:表级IS锁 + 行级S锁
-- 事务B(读取id=2)
BEGIN;
SELECT * FROM users WHERE id = 2 LOCK IN SHARE MODE;
-- 加:表级IS锁 + 行级S锁
-- ✅ 兼容!因为IS锁之间兼容
-- 事务A(修改id=1)
BEGIN;
UPDATE users SET name = 'A' WHERE id = 1;
-- 加:表级IX锁 + 行级X锁
-- 事务B(想读整个表)
BEGIN;
LOCK TABLES users READ; -- 尝试加表级S锁
-- ❌ 等待!因为IX和S不兼容
-- 事务A(修改id=1)
BEGIN;
UPDATE users SET name = 'A' WHERE id = 1;
-- 加:表级IX锁 + 行级X锁(id=1)
-- 事务B(修改id=2)
BEGIN;
UPDATE users SET name = 'B' WHERE id = 2;
-- 加:表级IX锁 + 行级X锁(id=2)
-- ✅ 兼容!因为IX锁之间兼容,且操作不同行
-- 查看当前锁信息
SELECT * FROM information_schema.INNODB_LOCKS;
SELECT * FROM information_schema.INNODB_LOCK_WAITS;
-- 或者使用
SHOW ENGINE INNODB STATUS\G;
-- 在输出中查找 "LOCK GRANT" 部分
| 特性 | 说明 |
|---|---|
| 表级锁 | 意向锁是加在表上的,不是行 |
| 快速检查 | 避免全表扫描检查行锁 |
| 两种类型 | IS(意向共享)、IX(意向排他) |
| 兼容性 | IS和IX之间可以共存 |
| 自动管理 | MySQL自动加意向锁,无需手动操作 |
Q:意向锁会阻塞其他事务吗? A:意向锁之间不互斥(IS和IX兼容),但意向锁和某些表锁互斥。
Q:意向锁会影响性能吗? A:基本不影响。它实际上提升性能,避免了全表扫描检查行锁。
Q:所有存储引擎都有意向锁吗? A:不是!只有InnoDB有,MyISAM没有意向锁。
"意向锁是表的门卫,它不负责具体安保(行锁负责),只告诉访客:里面有人正在办事(IS/IX),你们先等等!"
理解意向锁,你就掌握了InnoDB锁机制的50%!它让表锁和行锁能够高效共存。