外观
这个锁是怎么记录的,存在哪里?
⭐ 题目日期:
快手 - 2024/12/29
📝 题解:
在 InnoDB 存储引擎中,锁的管理和记录是通过 内存数据结构 和 事务系统 实现的。锁信息不会持久化到磁盘,而是存储在内存中,并通过事务的生命周期动态管理。以下是锁的记录方式和存储位置的详细说明:
一、锁的存储位置
1. 内存中的锁结构
- 锁对象(Lock Struct): InnoDB 为每个被锁定的资源(如行记录、间隙)在内存中创建一个锁结构(
lock_t
),包含以下信息:- 锁类型:行锁(Record Lock)、间隙锁(Gap Lock)、临键锁(Next-Key Lock)等。
- 事务信息:持有该锁的事务指针(
trx_t
)。 - 锁定的资源标识:如记录的索引位置、间隙范围。
- 锁模式:共享锁(S锁)或排他锁(X锁)。
- 全局锁表(Lock Table): 所有活跃的锁对象通过哈希表组织,哈希键由 锁定的资源标识(如空间 ID、页号、记录位置)生成,便于快速查找。
2. 事务系统
- 事务对象(trx_t): 每个事务维护一个锁链表,记录该事务持有的所有锁对象。
- 事务提交或回滚时,会遍历链表释放所有锁。
3. 数据字典
- 索引结构: InnoDB 的索引(B+树)中存储了记录的物理位置信息,锁的申请基于索引定位到具体的记录或间隙。
二、锁的记录方式
锁的具体记录方式与 索引类型 和 锁定范围 密切相关:
1. 行锁(Record Lock)
- 锁定目标:索引中的具体记录(主键或二级索引)。
- 记录方式:
- 对主键索引的记录加锁时,直接锁定主键对应的行。
- 对二级索引的记录加锁时,会同时锁定二级索引项和对应的主键索引项(防止通过其他索引路径修改数据)。
2. 间隙锁(Gap Lock)
- 锁定目标:索引记录的间隙范围(区间)。
- 记录方式:
- 例如,锁定
(5, 10)
的间隙,阻止其他事务插入id=6
到id=9
的值。 - 间隙锁仅存在于 REPEATABLE READ 隔离级别。
- 例如,锁定
3. 临键锁(Next-Key Lock)
- 锁定目标:行锁 + 间隙锁的组合(锁定记录及其之前的间隙)。
- 记录方式:
- 例如,锁定
(5, 10]
,即间隙(5, 10)
和记录10
。 - 默认的锁模式,用于防止幻读。
- 例如,锁定
三、锁的申请与释放流程
1. 申请锁
- 事务通过索引定位到需要锁定的记录或间隙。
- 检查内存中的锁表,判断是否存在冲突的锁(如其他事务已持有排他锁)。
- 若无冲突,创建锁对象并加入事务的锁链表和全局锁表。
- 若存在冲突,事务进入等待状态,直到锁被释放或超时。
2. 释放锁
- 事务提交或回滚: 释放事务持有的所有锁对象,并从全局锁表中删除。
- 显式释放: 某些场景下(如悲观锁提前释放),可通过
ROLLBACK
或COMMIT
释放锁。
四、锁的可见性与监控
1. 查看锁信息
通过以下方式监控当前锁状态:
SHOW ENGINE INNODB STATUS: 输出
TRANSACTIONS
部分,显示活跃事务和锁信息。SHOW ENGINE INNODB STATUS;
information_schema 系统表:
-- 查看当前活跃的锁 SELECT * FROM information_schema.INNODB_LOCKS; -- 查看锁等待关系 SELECT * FROM information_schema.INNODB_LOCK_WAITS;
2. 示例输出
--- TRX HAS BEEN WAITING 5 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 12345 page no 7 n bits 80 index PRIMARY of table `test`.`t`
trx id 67890 lock_mode X locks rec but not gap waiting
五、锁的优化与注意事项
- 索引设计:
- 为查询条件添加合适的索引,避免全表扫描导致的表级锁。
- 唯一索引减少间隙锁的冲突范围。
- 事务设计:
- 尽量缩短事务长度,减少锁持有时间。
- 避免在事务中执行耗时操作(如网络调用)。
- 隔离级别选择:
- 根据业务需求选择最低隔离级别(如
READ COMMITTED
可减少间隙锁)。
- 根据业务需求选择最低隔离级别(如
- 监控与调优:
- 定期检查锁等待和死锁日志(
SHOW ENGINE INNODB STATUS
)。 - 配置
innodb_lock_wait_timeout
控制锁等待超时时间。
- 定期检查锁等待和死锁日志(
六、总结
- 锁的存储:内存中的锁对象(
lock_t
)和事务系统(trx_t
)动态管理。 - 锁的记录:基于索引结构,通过行锁、间隙锁、临键锁保护数据完整性。
- 核心价值:通过细粒度锁机制实现高并发事务的隔离性,但需合理设计索引和事务,避免性能问题。