MySQL中的锁机制
一、按锁粒度分类
- 行级锁(Row-Level Lock)
- 共享锁(S Lock):允许事务读取一行,阻止其他事务获取相同行的排他锁。
- 用法:
SELECT ... FOR SHARE;
(MySQL 8.0+,旧版用LOCK IN SHARE MODE
)。
- 用法:
- 排他锁(X Lock):允许事务更新/删除行,阻止其他事务获取任何锁。
- 用法:
SELECT ... FOR UPDATE;
或自动加在UPDATE
/DELETE
语句中。
- 用法:
- 适用场景:高并发写操作,InnoDB默认使用行锁。
- 共享锁(S Lock):允许事务读取一行,阻止其他事务获取相同行的排他锁。
- 表级锁(Table-Level Lock)
- 表锁:锁定整张表。
- 显式加锁:
LOCK TABLES table_name READ/WRITE;
(MyISAM默认)。 - 隐式加锁:MyISAM在查询时加读锁,写时加写锁。
- 显式加锁:
- 意向锁(Intention Lock):表级锁,表示事务即将对表中的行加锁。
- 意向共享锁(IS):事务准备对某些行加共享锁。
- 意向排他锁(IX):事务准备对某些行加排他锁。
- 适用场景:MyISAM表或需要批量操作时手动加锁。
- 表锁:锁定整张表。
- 全局锁(Global Lock)
- 锁定整个数据库实例,通过
FLUSH TABLES WITH READ LOCK;
实现,用于备份。
- 锁定整个数据库实例,通过
二、特殊锁类型
- 间隙锁(Gap Lock)
- 锁定索引记录之间的间隙,防止幻读。
- 用法:在可重复读(RR)隔离级别下,自动加在范围查询的间隙,如
SELECT * FROM t WHERE id BETWEEN 10 AND 20 FOR UPDATE;
。
- Next-Key Lock
- 行锁 + 间隙锁的组合,锁定左开右闭区间(如
(10, 20]
)。 - 适用场景:InnoDB在RR隔离级别下默认使用,防止幻读。
- 行锁 + 间隙锁的组合,锁定左开右闭区间(如
- 插入意向锁(Insert Intention Lock)
- 一种特殊的间隙锁,表示事务准备在某个间隙插入记录。
- 特点:允许不同插入位置的锁共存,但会等待冲突的间隙锁释放。
- 自增锁(AUTO-INC Lock)
- 针对自增列的表级锁,保证自增值唯一。
- 优化:MySQL 8.0+使用轻量级互斥量替代,提升并发性。
- 元数据锁(Metadata Lock, MDL)
- 自动加锁,防止DDL(如
ALTER TABLE
)与DML冲突。 - 注意:长事务可能阻塞表结构变更。
- 自动加锁,防止DDL(如
- 记录锁(Record Lock)
- 锁定索引中的某条记录(主键或唯一索引)。
- 用法:
SELECT * FROM t WHERE id=1 FOR UPDATE;
。
三、锁的使用场景与注意事项
- 显式加锁: sql 复制 -- 加行级排他锁 SELECT * FROM table WHERE id=1 FOR UPDATE; -- 加行级共享锁(MySQL 8.0+) SELECT * FROM table WHERE id=1 FOR SHARE; -- 加表锁(谨慎使用) LOCK TABLES table_name WRITE; UNLOCK TABLES;
- 隐式加锁:
- InnoDB在
UPDATE
/DELETE
时自动加行级排他锁。 - MyISAM在写操作时自动加表级写锁。
- InnoDB在
- 死锁处理:
- MySQL自动检测死锁并回滚代价较小的事务。
- 避免方法:按顺序访问资源、减少事务大小、使用低隔离级别(如RC)。
- 隔离级别影响:
- 读已提交(RC):无间隙锁,可能幻读。
- 可重复读(RR):默认使用Next-Key锁,防止幻读。
四、总结
锁类型 | 作用范围 | 典型场景 | 示例语句 |
---|---|---|---|
行级锁(S/X) | 单行 | 高并发读写 | SELECT ... FOR UPDATE |
表锁 | 整表 | MyISAM或批量操作 | LOCK TABLES ... WRITE |
间隙锁 | 索引间隙 | 防止幻读(RR级别) | 范围查询FOR UPDATE |
元数据锁 | 表结构 | DDL操作 | ALTER TABLE |
自增锁 | 自增列 | 插入自增主键 | INSERT INTO t VALUES(...) |
合理选择锁机制可有效平衡并发性能与数据一致性。建议优先使用InnoDB的行级锁,避免长事务和大范围锁,同时根据业务需求调整隔离级别。