LAB 3 并发控制
实验概述
本次实验主要关注于数据库系统的并发控制,重点关注于基于MVCC技术的多线程事务处理。通过实现MVCC机制实现多线程情况下的并发事务处理,让同学们对于数据库系统中并发控制机制有进一步的理解。
实验任务
本次实验主要有3个任务:
- 修改CheckPointLog接口,增加当前事务编号的存储和恢复过程。
- 设置和获取记录隐藏列,添加对应的接口。
- 修改PageHandle,实现多线程情境下的记录页面控制。
- 修改Table接口,实现适应MVCC场景的增删改查。
实验开始前,请按照文档中更新说明中的步骤合并新增代码。
相关模块
- tx/lock_manager: 锁管理服务,可以定义并操作共享锁。可以用于保护数据页面的读写并发。
- tx/signal_manager: 信号管理服务,可以定义信号并等待信号。可以利用信号机制控制不同线程之间的执行顺序。
基础功能实现顺序
- log/checkpoint_log: 增加当前事务编号的存储和恢复过程。
- record/record_factory: 添加操作隐藏列的接口。
- table/page_handle.cpp: 实现多线程场景下的记录页面的插入、删除和查找。
- table/table.cpp: 修改多线程场景下的表的插入、删除和更新。
测试说明
本次实验主要考察并发过程中事务之间的隔离性问题,通过多版本并发控制实现快照隔离,测试中增加了 declare, enddecl, signal, wait, run 等指令。
declare 和 enddecl 用于声明一个事务块,定义一个事务所包含的 SQL 语句,但并不执行这些 SQL。
run 用于并发执行事务,如 run t1, t2, t3 表示并发执行 t1, t2, t3 三个事务。
wait 和 signal 用于控制事务之间的并发,wait t1_2 表示等待信号 t1_2,其他事务可以通过 signal t1_2 发出信号 t1_2,从而使等待信号 t1_2 的事务继续进行。
可选高级功能
不要求将高级功能集成到主分支中,建议单开分支完成实验。但是建议同学们设计验证自己实验结果的测例并给出测试的可视化结果展示。
MVCC 的垃圾回收(1分)。由于 MVCC 机制中删除操作并没有真正删除对应的记录,仅仅标记了相应记录对应的版本号,使系统存在一些不需要的垃圾数据。设计算法回收垃圾数据所占用的空间,说明算法设计的要点,如垃圾回收的时机,垃圾数据的判定方法等,并需设计测例证明垃圾回收前后存储空间的变化情况。
写写冲突的处理(2分:1分基础+1分死锁)。当前测例仅包含读写冲突,在 MVCC 并发控制机制下不会发生阻塞,设计算法正确处理并发条件下的写写冲突问题,需详细给出写写冲突的处理方法,尤其是涉及死锁问题的处理(死锁占1分,死锁检测或死锁避免方法均可),并设计测例证明算法正确性(无死锁测例+有死锁测例,建议画一下测例的并发流程图)。
高级功能满分3分。
框架错误说明
经同学指出,目前的实验框架存在如下错误:
table.cpp 的 InsertRecord 函数中,首先读取了表的元信息,确定插入记录的 page_id 和 slot_id 等,插入后对表的元信息进行了更新,这些操作没有对元信息进行加锁,可能导致多个线程同时插入数据时产生错误。
UpdateRecord 函数在实验3中拆分成了 DeleteRecord + InsertRecord 两个部分,而 UpdateNode 是通过 ScanNode 的 Next 方法以页为粒度进行 LoadRecords 操作。假设 page 0 已满,且有一个 record 需要 update,由于 delete 不会真正将 page 0 的 record 删除,新的 insert 会被插入 page 1,此时 UpdateNode 会调用 Next 函数对 page 1 进行 LoadRecords 操作,新插入的记录会被重新 delete + insert 一次。在本次实验的测例中,该错误不会影响正确性,但如果一页只能存放一个 record,该错误会造成死循环。
以上错误不影响基础功能的实现与测试,也不会对后续实验产生影响,由于修复错误需要对框架进行较大幅度的改动,可能影响已经完成实验的同学的评测结果,本学期暂不对以上错误进行修复,感谢同学对框架错误的反馈。
截止时间
2023 年 4 月 23 日(第九周周日)晚 23:59 分。