MySQL 的锁类型有哪些?(最全总结)
MySQL 的锁机制比较复杂,涉及不同层级、不同引擎、不同业务场景。
为了帮助你更系统地理解,我把 MySQL 的锁分类拆成 4 个大方向:
一、按锁的“粒度”分类(最常见)
1. 表级锁(Table Lock)
锁住整张表,粒度大,开销小,冲突多。
适用场景:MyISAM、DDL 操作。
特点:
-
• 加锁速度快 -
• 并发能力低 -
• 写时阻塞读,读时阻塞写
2. 行级锁(Row Lock)✔ InnoDB 使用最广泛
粒度小,只锁住需要的数据行,并发能力高。
包括:
-
• 行共享锁(S Lock) -
• 行排他锁(X Lock)
特点:
-
• 并发性能好 -
• 加锁成本高 -
• 可能出现死锁
3. 页级锁(Page Lock)
介于表锁和行锁之间。
常见于:BDB 引擎(已很少用)
二、按锁的“读写”性质分类
1. 共享锁(Shared Lock,S 锁)
允许其他事务读,但不允许写。
SQL:
SELECT * FROM t WHERE id = 1 LOCK IN SHARE MODE;
效果:
-
• 自己能读 -
• 别人能读 -
• 别人不能写
2. 排他锁(Exclusive Lock,X 锁)
独占锁,只允许自己读写,别人无法读写。
SQL:
SELECT * FROM t WHERE id = 1 FOR UPDATE;
或:
UPDATE t SET ... WHERE id = 1;
效果:
-
• 自己能读写 -
• 别人不能读写
三、按“意向”分类(InnoDB 特有)
1. 意向共享锁(IS)
表示“我要加 S 锁,但还没加”,加在表上。
2. 意向排他锁(IX)
表示“我要加 X 锁”,加在表上。
为什么需要意向锁?
提高 InnoDB 的加锁效率,避免遍历每一行判断是否有锁。
例:
-
• 一行被加 X 锁 → 表上必须有 IX -
• 一行被加 S 锁 → 表上必须有 IS
四、InnoDB 特有的行级锁(考试/面试必问)
1. 记录锁(Record Lock)
锁住某一条记录(索引)。
例:
SELECT * FROM user WHERE id = 10 FOR UPDATE;
锁住 id=10 的索引项。
2. 间隙锁(Gap Lock)
锁住两个索引记录之间的“空隙”,用于防止插入:
用于防止幻读。
例:
id ∈ (10, 20) 之间
锁的是“范围”,不是某条记录。
3. 临键锁(Next-Key Lock) ✔ 默认模式
= 记录锁 + 间隙锁(左开右闭区间)
例如:
(10, 20]
用途:避免幻读。
4. 插入意向锁(Insert Intention Lock)
多个事务插入同一个 gap 时使用。
它们之间不互斥,不会阻塞彼此,InnoDB用它提升效率。
5. 自增锁(AUTO-INC Lock)
当表里有 AUTO_INCREMENT 主键时,插入场景用到。
两种模式:
-
• 表级(默认) -
• 轻量锁(innodb_autoinc_lock_mode=2)
五、按“是否阻塞”分类
1. 乐观锁(Optimistic Lock)
不依赖数据库锁,通常用 **版本号(version)**实现。
适合:冲突少的场景。
例:
UPDATE t SET num=num+1, version=version+1
WHERE id=1 AND version=100;
2. 悲观锁(Pessimistic Lock)
依赖数据库加锁,假设会冲突。
典型:
SELECT ... FOR UPDATE;
适合:并发高、冲突频繁的场景。
六、按“DDL/DML”分类
1. 元数据锁(MDL Lock)
MySQL 5.5+ 引入,对表结构的读写保护。
读锁:DML(SELECT/INSERT/UPDATE)
写锁:DDL(ALTER TABLE)
现象:
-
• 有长事务 → 阻塞所有 ALTER -
• 有 ALTER → 阻塞所有写入
2. 备份锁(Backup Lock)
用于在线备份,保护数据一致性。
七、加锁总结表(最常用)
八、总结
MySQL 的锁包括表级锁、行级锁和页锁。
InnoDB 使用行级锁,包含共享锁、排他锁、意向锁、记录锁、间隙锁、临键锁、插入意向锁和自增锁等。
除此,还有元数据锁(MDL)用于保护表结构。
不同锁在性能与并发上的目标不同,最常用的是行级锁中的 X 锁、S 锁和 Next-Key Lock。

