MYDB仿MySQL手写数据库项目总结

声明:该项目是一个开源项目,我是在学习该项目,该项目的github地址如下:

MYDB项目地址:https://github.com/CN-GuoZiyang/MYDB

MYDB项目采用C/S结构,支持启动一个服务器,并有多个客户端去连接,通过socket通信。

不算解析器的话,该项目分为五个模块:

transaction manager(TM):通过维护XID文件来维护事务的状态,并提供接口供其他模块来查询事务的状态。

data manager(DM):管理数据库的DB文件和日志文件。

version manager(VM):基于两段锁协议实现调度序列的可串行化,并实现MVCC以消除读写阻塞,实现两种隔离级别。

index manager(IM):实现B+树索引。

Table manager(TBM):实现对字段和表的管理,同时解析SQL语句,并根据语句操作表。

项目亮点:

一、基于Java NIO实现数据页的读写管理模块,数据访问效率比第一版的传统I/O快三倍

NIO 是 Java SE 1.4 引入的一组新的 I/O 相关的 API,它提供了非阻塞式 I/O、选择器、通道、缓冲区等新的概念和机制。相比与传统的 I/O 多出的 N 不是单纯的 New,更多的是代表了 Non-blocking 非阻塞,NIO具有更高的并发性、可扩展性以及更少的资源消耗等优点。

NIO是同步非阻塞的,服务器实现模式为 一个线程处理多个连接。服务端只会创建一个线程负责管理Selector(多路复用器),Selector(多路复用器)不断的轮询注册其上的Channel(通道)中的 I/O 事件,并将监听到的事件进行相应的处理。每个客户端与服务端建立连接时会创建一个 SocketChannel 通道,通过 SocketChannel 进行数据交互。

详细认识NIO可以看一下另一个博主写的一篇博客很详细:Java NIO 详解-CSDN博客

二、设计日志模块,采用WAL机制操作日志,支持数据库宕机后数据恢复

什么是WAL机制?

WAL(Write-Ahead Logging,预写式日志) 是一种用于保证数据库事务持久性(Durability)原子性(Atomicity) 的核心机制。其核心思想是:在修改数据之前,先将修改操作记录到日志中,再将数据写入磁盘。即使系统崩溃,也能通过日志恢复未完成的操作。

WAL的核心流程

  1. 事务提交时

    • 将事务的修改操作(如插入、更新、删除)按顺序追加写入日志文件(WAL文件)。

    • 日志写入成功后,事务才被视为已提交

  2. 数据写入磁盘

    • 实际的数据文件(如数据库表文件)的修改可以异步完成,无需立即写入。
  3. 崩溃恢复

    • 系统重启后,通过重放(Replay)日志文件,将未落盘的操作重新应用到数据文件中,确保数据一致性。

数据恢复:

因为MYDB要实现多线程下的工作方式:

所以为了确保数据恢复时能够正确恢复,我们要限制数据库的操作,有以下两种规定:

规定1:正在进行的事务,不会读取其他任何未提交事务产生的数据。

规定2:正在进行的事务,不会修改其他任何未提交的事务修改或产生的数据。

这样数据库崩溃时恢复数据就很简单了:

1.重做所有崩溃时已经完成(已经提交或需要回滚)的事务。

2.撤销所有崩溃时未完成(未提交的)的事务。

redo:

  1. 正序扫描事务 T 的所有日志

  2. 如果日志是插入操作 (Ti, I, A, x),就将 x 重新插入 A 位置

  3. 如果日志是更新操作 (Ti, U, A, oldx, newx),就将 A 位置的值设置为 newx

undo:

  1. 倒序扫描事务 T 的所有日志

  2. 如果日志是插入操作 (Ti, I, A, x),就将 A 位置的数据删除

  3. 如果日志是更新操作 (Ti, U, A, oldx, newx),就将 A 位置的值设置为 oldx

三、实现事务管理以及MVCC并发控制,基于两阶段锁协议(2PL)确保事务串行化,支持读已提交、可重复读两种隔离机制

在VM模块,VM向上层模块提供记录作为最小操作单元,即Entry,结构为三部分:XMIN(创建该Entry的事务ID)、XMAX(删除该Entry的事务ID)、data(数据)。

什么是MVCC并发控制?

MVCC是多版本并发控制,简单来说就是为每一条记录都创建多个版本,用来实现可以在不加锁的情况下读写无阻塞,根据相关规则读取某个版本的数据。

两阶段锁协议(2PL)

当一个事务对一个记录正在操作时,即已经上锁了,若另一个事务也想操作该数据,只能进入阻塞状态直到当前事务释放锁。

读已提交和可重复读可以去看我之前写的一篇博客:MySQL的事务原理及MVCC-CSDN博客

四、基于B+树构建索引结构,在 6 万条记录下索引查询耗时由原生遍历的 120ms 降至 1ms

对B+树结构索引不熟悉的可以看我写过的一篇博客:MySQL中的索引_innodb引擎默认索引-CSDN博客

五、构建表结构管理器,支持字段结构定义与 SQL 语句解析执行,支持多条件组合查询、插入、更 新等基本 SQL 语义操作

SQL解析是通过里面一个分割相关的类把SQL语句分割成不同的部分,比如关键字、字母下划线、字符串等等,然后通过praser解析类先来判断第一个部分的关键字,比如select、insert等等,然后把同一类的SQL交给不同的方法解析。

六、实现死锁检测机制,及时中止死锁事务,防止系统进入长时间等待状态

因为有两阶段锁协议(2PL),当一个事务对一个资源上锁之后,其他事务只能阻塞等待,而这样有死锁的可能,在项目中,我们把事务Ti等待事务Tj解锁抽象为一条有向边,即Ti->Tj,这样多条有向边就组成图,我们通过检查这个图是否是循环的,就可以来检查是否有死锁。

我们可以通过dfs来遍历图

思路:维护一个 xidStamp 哈希表,记录每个事务的时间戳。时间戳初始为1,每开启一轮新检测就自增。 对每个持有资源的事务(xid),如果未被当前轮次检测过(时间戳为空或旧值),则用新的时间戳发起DFS检查。如果DFS过程中遇到已被标记为当前时间戳的事务,说明形成了循环链,立即返回死锁。如果事务未等待任何资源(waitU中无记录),说明路径安全;如果所有事务遍历完均无环路,则系统无死锁。

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

相关推荐
码出财富37 分钟前
SQL语法大全指南
数据库·mysql·oracle
异世界贤狼转生码农2 小时前
MongoDB Windows 系统实战手册:从配置到数据处理入门
数据库·mongodb
QuZhengRong3 小时前
【数据库】Navicat 导入 Excel 数据乱码问题的解决方法
android·数据库·excel
码农阿豪3 小时前
Windows从零到一安装KingbaseES数据库及使用ksql工具连接全指南
数据库·windows
冷崖8 小时前
MySQL异步连接池的学习(五)
学习·mysql
时序数据说8 小时前
时序数据库市场前景分析
大数据·数据库·物联网·开源·时序数据库
听雪楼主.12 小时前
Oracle Undo Tablespace 使用率暴涨案例分析
数据库·oracle·架构
我科绝伦(Huanhuan Zhou)12 小时前
KINGBASE集群日常维护管理命令总结
数据库·database
妖灵翎幺12 小时前
Java应届生求职八股(2)---Mysql篇
数据库·mysql
HMBBLOVEPDX12 小时前
MySQL的事务日志:
数据库·mysql