本文共 2318 字,大约阅读时间需要 7 分钟。
InnoDB 是 MySQL 的一个高度可靠的存储引擎,特别适用于处理高并发和复杂的事务性数据应用。其锁机制是保证数据库一致性和高性能的关键组成部分。本文将深入探讨 InnoDB 的锁机制,包括 latch 与 lock 的实现、共享锁与排他锁的作用、行锁算法以及死锁案例分析。
InnoDB 的锁机制可以分为两大类:latch(闩锁)和 lock(数据库锁)。
Latch 被称为“轻量级锁”,其特点是获取和释放速度极快,适用于对短时间内对临界资源的控制。在 InnoDB 中,latch 又可以分为两种类型:
需要注意的是,InnoDB 没有死锁检测机制,开发者需要通过合理的锁定策略来避免死锁。
数据库提供的锁机制,用于锁定数据资源。与 latch 不同,lock 的持有时间通常较长,且数据库引擎会在事务提交或滚back 时释放资源。lock 具有死锁检测机制,能够在必要时自动解决死锁问题。
InnoDB 提供两种标准的行级锁:
此外,InnoDB 还支持意向锁:
InnoDB 提供三种行锁算法:
这些算法共同确保了在并发访问下数据的一致性和完整性。
在默认的 RR 隔离级别下,InnoDB 的行锁是对索引加锁,扫描过程中对边界行加锁。如果使用的是二级索引,除了对二级索引加锁,还需对主键聚簇索引加锁。
需要注意的是,InnoDB 在加锁时会锁定更多行数,尤其是在支持 Index Condition PushDown 的情况下(如 MySQL 5.6),这可能导致锁定数量远超实际需要的行数。
例如,语句 A 使用二级索引更新数据,语句 B 使用聚簇索引更新数据。如果 A 只对二级索引加锁,B 可能无法感知 A 的存在,违反了同一数据行更新必须串行执行的约束。因此,必须同时锁定主键和二级索引。
在不同的隔离级别下,select 操作对锁定机制有不同的影响:
插入操作会对插入成功的行加记录锁,不会阻止其他事务插入前一版本的数据。插入之前,会在间隙加意向锁。如果遇到 duplicate-key error,会对冲突记录加共享锁。这种情况下可能导致死锁,例如两个 insert 对同一记录的共享锁相互等待。
delete 操作仅设置 delete_flag 为 1,实际删除延迟到 purger 过程。delete 时:
更新操作对满足条件的记录加 next-key 锁。如果是等值匹配且使用唯一索引或聚簇索引,可以只加记录锁。需要注意 NULL 值的处理:在唯一索引中含 NULL 的记录不会加记录锁,而是加 next-key 锁。
以下是一个典型的死锁案例:
以下是一个死锁案例:
以下是一个死锁案例:
本文的内容参考了多个官方文档和实践经验,具体包括:
通过合理的锁定策略和优化数据库设计,可以有效避免死锁问题,提升数据库性能和可靠性。
转载地址:http://keffk.baihongyu.com/