并发
DBMS 需要允许多个线程安全地访问数据结构。
并发控制协议是 DBMS 用于确保共享对象上的并发操作得到“正确”结果的方法。
两个并发协议的标准
- Logical Correctness: 线程能否看到它应该看到的数据
- 数据内部是否还好
Locks VS. Latches
locks
- 保护数据库的逻辑内容免受其他事务的影响。
- 保证事务的持久性
- 需要能够回滚
Latches
- 保护 DBMS 内部数据结构的关键部分免受其他线程的影响。
- 保证操作的持久性
- 并不需要能够回滚
为什么Lock可以回滚而Latches不可以回滚?。
Locks是为了保护数据的一致性和完整性,当事务失败或需要回滚时,系统需要确保事务对数据的修改能够被撤销,从而维护数据库的一致性状态。
Latches主要是为了保护内部数据结构的完整性,不直接涉及用户数据的修改,因此不需要支持回滚操作。
Latch Modes
Read Mode
- 多个线程可以同时读取相同的数据
- 针对相同的数据,当别的线程已经获得处于 read mode 的 latch,新的线程也可以继续获取 read mode 的 latch
Write Mode
- 多个线程可以同时读取相同的数据
- 针对相同的数据,当别的线程已经获得处于 read mode 的 latch,新的线程也可以继续获取 read mode 的 latch
Hash Table Latching
由于线程访问数据结构的方式有限,因此易于支持并发访问。
- 所有线程都朝同一方向移动,并且一次仅访问单个页/槽。
- 不会死锁
调整表的大小,在整个表上使用全局写锁存器
- Page Latches
- 每个页面都有自己的读写器锁存器,可以保护其全部内容
- 线程在访问页面之前获取读或写锁存器。
- Slot Latches
- Page中的每个Slot都有自己的锁
- 可以使用单Latch来减少元数据和计算开销。
B+ Tree Concurrency Control
我们希望允许多个线程同时读取和更新 B+ Tree。
我们需要防范两类问题:
- 多个线程同时尝试修改节点的内容。
- 一个线程遍历树,而另一个线程拆分/合并节点。
Latch Carbbing/Coupling
允许多个线程同时访问/修改 B+Tree 的协议。
- 获取父节点的latch
- 获取子节点的latch
- 如果父节点安全释放latch
安全节点是指更新时不会分裂或合并的节点。
- 插入后未满
- 删除后满足半满
Find:从根节点开始,沿着树向下遍历
- 在子节点上获取R Latch
- 解锁父节点
- 从夫直到要查找的节点
Insert/Delete:从根开始向下,根据需要获取 W 个Latchs。 一旦子节点被锁住,检查是否安全:
- 如果子节点安全。释放所有祖先
出现的问题:每次在根节点上取写锁存器成为并发较高的瓶颈
Better Latching Algorithm(乐观锁)
B+ Tree 的大多数Insert/Delete不需要拆分或合并,所有并不假设会有拆分/合并,而是使用读锁存器乐观地遍历树。
Search:同Latch Carbbing/Coupling
Insert/Delete
- 同Search一样latch,到达叶子节点时,在叶子节点上设置W锁
- 如果叶子节点不安全,释放所有Latch,并且使用Latch Carbbing/Coupling的Insert/Delete的W Latch 重置线程
这种方法乐观地假设只有叶节点会被修改; 如果不是,则在第一次传递到叶子时设置的 R Latch是浪费的。
如果一个线程需要从一个节点转移可能会导致死锁问题。