在 MySQL 中,锁(Locks)是为了保证数据的一致性和完整性而设计的机制。常见的锁可以从粒度和操作类型两个角度分类。以下是详细介绍:
按 粒度 分类
1. 全局锁
- 描述:锁定整个数据库实例。
- 用途:主要用于备份,如
FLUSH TABLES WITH READ LOCK (FTWRL)
。 - 特点:
- 整个数据库处于只读状态。
- 对性能影响较大,通常不建议在线使用。
2. 表级锁
- 描述:锁定整个表,防止其他线程对表进行操作。
- 类型:
- 表锁:使用
LOCK TABLES
语句显式加锁。 - 元数据锁(MDL, Metadata Lock):
- 自动加锁,例如
ALTER TABLE
时。 - 防止表结构在读写操作时被修改。
- 自动加锁,例如
- 表锁:使用
- 特点:
- 并发性较低,因为锁住了整个表。
3. 行级锁
- 描述:对特定行记录加锁,主要由 InnoDB 引擎支持。
- 优点:粒度最小,并发性能高。
- 实现方式:
- 基于索引加锁。如果没有索引,行锁会退化为表锁。
- 适用场景:高并发环境。
按 操作类型 分类
1. 共享锁(S 锁,Shared Lock)
- 描述:允许多个事务同时读取,但禁止写入。
- 使用方式:通过
SELECT ... LOCK IN SHARE MODE
显式加锁。 - 适用场景:
- 需要读取数据并防止数据被其他事务修改时。
- 例如检查数据后基于条件执行写操作。
2. 排他锁(X 锁,Exclusive Lock)
- 描述:一个事务持有排他锁后,其他事务不能再读取或修改该记录。
- 使用方式:通过
FOR UPDATE
显式加锁,或隐式加锁(如INSERT
、UPDATE
)。 - 适用场景:
- 修改数据时确保线程安全。
按 意图 分类(InnoDB 专属)
为了提高加锁效率,InnoDB 提供了意向锁(Intent Locks),与表锁结合使用:
- 意向共享锁(IS 锁):事务准备在某行加共享锁前先获取表的 IS 锁。
- 意向排他锁(IX 锁):事务准备在某行加排他锁前先获取表的 IX 锁。
- 作用:快速判断是否能对整张表加锁,避免扫描整表。
其他特殊锁
1. 间隙锁(Gap Lock)
- 描述:锁住索引间隙,而不是具体的行。
- 用途:防止幻读问题,保证事务的可重复读(REPEATABLE READ)。
- 场景:例如在范围查询中,锁住范围内不存在的记录。
2. 临键锁(Next-Key Lock)
- 描述:行锁 + 间隙锁的组合。
- 用途:解决可重复读(REPEATABLE READ)隔离级别下的幻读问题。
3. 自增锁(AUTO-INC Lock)
- 描述:对含有自增列的表加特殊锁,保证自增列的生成顺序。
- 特点:独占锁,直到当前事务完成。
4. 死锁检测锁
- 描述:通过检测锁的相互等待关系来判断是否存在死锁。
总结
- 全局锁:适用于全局操作,如备份。
- 表级锁:适用于表的结构变更或全表操作。
- 行级锁:适用于高并发写入。
- 间隙锁和临键锁:解决幻读问题。
- 意向锁:优化加锁性能。
在实际开发中,应根据场景选择适当的锁类型,以平衡数据一致性和并发性能。