MySQL 锁的分类
MySQL 锁机制用于保证并发事务的数据一致性,按粒度分为全局锁、表锁和行锁。
锁的分类概览
| 类型 | 粒度 | 性能 | InnoDB支持 |
|---|---|---|---|
| 全局锁 | 整库 | 最低 | 不支持 |
| 表级锁 | 整表 | 较低 | 支持 |
| 行级锁 | 行 | 较高 | 支持(核心) |
全局锁
SQL
-- 锁定整个数据库,只读
FLUSH TABLES WITH READ LOCK;
-- 全库只读,无法写入
INSERT INTO users VALUES ...; -- 阻塞
-- 解锁
UNLOCK TABLES;
用途:全库逻辑备份、主从复制初始化。
全局锁影响整个数据库,生产环境慎用。
表级锁
表锁
SQL
-- 读锁(共享锁)
LOCK TABLE users READ;
-- 可读,不可写
SELECT * FROM users; -- 正常
INSERT INTO users ...; -- 阻塞
UNLOCK TABLES;
-- 写锁(排他锁)
LOCK TABLE users WRITE;
-- 当前会话可读写,其他会话阻塞
INSERT INTO users VALUES ...;
UNLOCK TABLES;
元数据锁(MDL)
SQL
-- MDL 自动加锁,保护表结构
-- 事务A 事务B
START TRANSACTION;
SELECT * FROM users;
ALTER TABLE users ADD COLUMN age INT; -- 阻塞
COMMIT;
-- 事务A提交后才能执行DDL
意向锁
SQL
-- InnoDB 自动加意向锁
-- 事务对某些行加行锁时,自动在表上加意向锁
-- 防止其他事务加表锁
-- 意向共享锁(IS)
SELECT * FROM users WHERE id=1 LOCK IN SHARE MODE;
-- 意向排他锁(IX)
UPDATE users SET name='新' WHERE id=1;
行级锁
共享锁(S锁)
SQL
-- 读锁,允并发读
SELECT * FROM users WHERE id = 1 LOCK IN SHARE MODE;
-- 其他事务可读但不可写
-- 事务A 事务B
SELECT * FROM users WHERE id=1 LOCK IN SHARE MODE;
SELECT * FROM users WHERE id=1 LOCK IN SHARE MODE; -- OK
UPDATE users SET name='x' WHERE id=1; -- 阻塞
排他锁(X锁)
SQL
-- 写锁,独占访问
SELECT * FROM users WHERE id = 1 FOR UPDATE;
UPDATE users SET name = '新' WHERE id = 1;
DELETE FROM users WHERE id = 1;
-- 其他事务读写都阻塞
记录锁、间隙锁、临键锁
SQL
-- 记录锁:锁单行
UPDATE users SET name='a' WHERE id=1;
-- 间隙锁:锁间隙,防止幻读(RR级别)
-- 锁 (5, 10) 间隙,防止插入 id=7
SELECT * FROM users WHERE id BETWEEN 5 AND 10 FOR UPDATE;
-- 临键锁:记录锁 + 间隙锁(RR默认)
SELECT * FROM users WHERE id=5 FOR UPDATE;
-- 锁住 id=5 和 (5, 10) 间隙
锁兼容矩阵
| S锁 | X锁 | IS | IX | |
|---|---|---|---|---|
| S锁 | ✓ | ✗ | ✓ | ✗ |
| X锁 | ✗ | ✗ | ✗ | ✗ |
| IS | ✓ | ✗ | ✓ | ✓ |
| IX | ✗ | ✗ | ✓ | ✓ |
查看锁信息
SQL
-- 查看当前锁
SHOW ENGINE INNODB STATUS;
-- 使用 performance_schema
SELECT * FROM performance_schema.data_locks;
SELECT * FROM performance_schema.metadata_locks;
要点总结
- 全局锁锁定整个库,用于备份场景
- 表锁粒度大,并发性低,MyISAM 主要用表锁
- 行锁粒度小,并发性高,InnoDB 核心特性
- 共享锁允许并发读,排他锁独占访问
- RR 级别通过间隙锁和临键锁防止幻读
📝 发现内容有误?点击此处直接编辑