ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

10-数据库学习笔记(数据结构中的锁机制)

10-数据库学习笔记(数据结构中的锁机制) 一.索引并发控制整体技术背景1.技术诞生背景B 树、哈希表这些索引结构默认都是「只有一个人操作」的单线程理想情况—— 就像你独自用自己的办公桌想怎么翻文件、怎么整理文件夹都随便不会有人抢、不会有人干扰。但真实的数据库是多核 CPU、多用户同时访问的必须让很多线程同时读写同一个索引。这么做一是为了榨干多核性能二是为了 “隐藏磁盘 IO 的等待”—— 磁盘读数据很慢与其让线程傻等不如先让别的线程干活。若缺乏并发控制机制会出现两类核心正确性问题逻辑正确性异常读到脏的、半截的数据物理结构损坏直接把索引本身给搞散架2.并发控制的正确性要求逻辑正确性线程只能读取当前事务/操作可见的合法数据无脏读、幻读等异常物理正确性确保数据结构的内部表示始终处于有效状态如 B 树节点的指针不被破坏、链表无断链等这正是 Latch 需要解决的核心问题二、闩锁Latch核心基础体系1. 闩锁与事务锁的核心区别(1)技术背景数据库有两套完全不一样的并发控制机制事务锁 Lock 面向上层业务事务闩锁 Latch 面向底层内核数据结构。它们的管控层次、存活周期、使用场景均不相同(2)核心逻辑对比锁Lock与闩锁Latch的对比是数据库内核并发的重点知识二者关键区别整理如下管控对象Lock 用于隔离多个并发事务Latch 用于隔离数据库内部各个工作线程。保护对象Lock 防护磁盘上的业务逻辑数据Latch 保护驻留内存的索引、缓冲页这类内核数据结构。持有周期Lock 的有效期覆盖完整事务事务结束才释放Latch 只在临界代码执行期间持有操作结束马上释放。回滚特性Lock 可以跟随事务完成回滚Latch 只负责维护结构完整性不参与事务回滚。死锁处理Lock 通过死锁检测、超时机制、事务中止来化解死锁Latch 依靠编码规范从设计上避免死锁发生。存储位置Lock 交由锁管理器集中维护Latch 直接挂载在受保护的内核结构之上。(3)优缺点与实际落地表现优点双层并发控制机制分工明确。事务锁 Lock 负责保证上层业务事务的逻辑一致性闩锁 Latch 维护数据库内核底层结构的物理完整性同时兼顾业务逻辑正确和系统运行稳定。缺点闩锁不提供死锁检测能力只能依靠开发时的编码规范规避死锁问题开发实现难度大系统容错能力较弱。通俗示例事务锁相当于图书馆的借阅权限管控锁约束各个读者对应事务的借书行为闩锁则是书架整理时的防护锁约束管理员对应工作线程调整整理书架索引结构防止整理操作中途造成书架结构损坏。2.闩锁工作模式与兼容性(1)技术背景多线程访问索引结构分为读、写两类操作读操作可并发执行写操作需要独占资源。为最大化并发性能、减少不必要的阻塞闩锁设计了读写两种工作模式及兼容机制。(2)核心逻辑读模式Read允许多个线程同时获取读闩锁支持并发读取线程之间不会互相阻塞。写模式Write属于独占访问模式。只要已有线程持有读闩锁或者写闩锁其他线程就不能成功加写闩锁同一时刻只允许一个线程执行修改操作。兼容性规则读‑读可以共存读‑写相互排斥写‑写相互排斥。(3)优缺点优点充分释放读并发能力适配数据库读多写少场景提高系统吞吐量锁逻辑简单执行效率高。缺点读锁若长时间不释放会一直挡住写请求。3.闩锁设计目标与主流实现方案(1)技术背景闩锁是数据库内核高频使用的基础组件它的内存消耗和执行效率直接约束数据库并发能力所以闩锁要做到轻量、无冲突时快速运行、去中心化。(2)核心设计目标内存开销低闩锁依附于海量的索引节点每个闩锁都要尽量少占内存。无冲突快速路径没有线程竞争是常态加锁解锁逻辑必须飞快不能造成性能瓶颈。去中心化闩锁跟着节点走不需要全局管理器消除单点瓶颈。(3)主流实现方案测试并设置自旋闩锁TAS基于CPU原子指令实现加解锁仅需单指令无冲突效率极高但不支持缓存友好、高并发下自旋浪费CPU无法扩容。阻塞式OS互斥锁基于系统futex实现使用简单但每次加解锁约25ns并发扩展性差高竞争下线程阻塞开销大。读写闩锁支持并发读通过读写队列避免饥饿可基于自旋锁二次封装但需要维护队列状态存在少量开销。(4)优缺点总结自旋锁适合低竞争、短临界区场景OS互斥锁适合高竞争、长临界区场景自适应闩锁综合性能最优是现代数据库内核主流选型。三.哈希表索引并发控制机制1.技术背景哈希表的访问模式天生利于并发优化线程访问哈希表只做单向寻址每次仅访问一个槽位或一页没有跨页的复杂遍历。因此哈希表并发不容易出现死锁开发难度比 B 树小很多。不过全局锁会严重压制并发性能于是出现了多种粒度的闩锁实现方案。2.三类核心实现方式1全局闩锁方案整表共用一把锁。实现最简单并发性能最差内存开销极小仅适用于小表、原型验证场景。2页/块级闩锁方案按数据页独立加锁。粒度适中不同页可并行操作贴合磁盘 IO 特性是磁盘哈希索引最常用的折中方案。3槽位级闩锁方案每个哈希槽独立加锁。并发性能最强、锁竞争最小但实现复杂、锁本身内存开销大适用于内存哈希、高并发场景。四.B树索引并发控制核心协议1.技术背景B 树作为数据库的核心索引结构复杂度远高于哈希表。线程访问 B 树需要自顶向下逐层遍历节点且写入操作会触发节点分裂、合并与数据迁移等结构性变更存在遍历操作与结构修改之间的并发冲突。若不加以管控会出现遍历中途节点被拆分、数据丢失、树结构损坏等严重问题因此需要设计专属的 B 树并发闩锁协议。需要解决两类核心问题多线程同时修改同一节点线程遍历树时其他线程修改节点结构2.闩锁耦合协议这是 B 树并发控制的核心协议通过「边加锁边解锁」兼顾结构安全与并发性能核心三点加锁规则严格自上而下、先父后子加锁所有线程遵循统一加锁顺序从根源避免死锁。安全节点判定插入场景下节点未满、删除场景下节点数据过半即为安全安全节点操作后不会触发分裂 / 合并不会牵连上层节点。释锁规则获取子节点锁并确认其安全后立即释放所有祖先节点的锁大幅缩短锁持有时间提升整体并发度。3.悲观耦合协议缺陷与优化方案悲观协议 默认写操作一定会触发结构变动全程加写锁乐观优化 默认大概率不会触发结构变动先读锁遍历不行再回退1缺陷背景传统悲观耦合协议存在两个核心问题根节点成为全局瓶颈每次更新都从根节点开始加写锁而根节点全局唯一高并发下所有写操作都争抢这一把锁直接卡死整体并发上限。策略过度保守实际业务中绝大多数 B 树修改只改动叶子节点的数据根本不会触发节点分裂、合并完全不需要锁住上层节点。悲观策略全程持写锁白白浪费了大量并发能力。2乐观闩锁优化算法核心逻辑基于绝大多数修改不会引发结构变动的统计规律做乐观假设先用低成本的读锁遍历到叶子节点再升级写锁修改只有真的触发结构变化时才回退走完整的悲观写锁流程。
返回列表