持久化数据库实现:确保数据持久性与可靠性

我们的数据库能让你轻松插入和读取数据,但这些数据仅在程序运行时有效。一旦程序终止或重启,所有数据都将消失。然而,我们期望的数据库行为并非如此。以下是一个关于数据持久化的spec测试:

持久化的需求 :我们期望数据库能够在关闭连接后继续保留数据,这需要持久化保存至磁盘。

测试描述:"在关闭连接后,数据仍能得以保留。"

执行流程:

  1. 运行脚本,执行".exit"命令,关闭数据库连接。

  2. 验证结果,确保输出中包含"db > Executed."和"db > "两部分内容。

在后续的测试中,我们将看到如何实现数据持久化到磁盘,确保即使程序终止或重启,数据也能得以保留。

持久化实现方法 :采用类似序列化行数据的方式,将内存中的数据块写入文件,确保在程序重启时数据依然有效。

"Executed."

"db> "

end

◆ 持久化与SQLite

与SQLite相似,我们采用持久化技术,将整个数据库保存至单一文件中。我们已将行数据序列化为适当大小的内存块。为增强数据库的持久性,我们仅需将这些内存块写入文件,并在程序重启时从文件中读取。

  1. 持久化技术及实现
2.1 ◆ 持久化结构解析

我们的程序与SQLite架构的契合之处在于其数据访问方式。当表对象需要数据页时,它会通过pager进行请求。pager不仅访问页缓存,还与文件进行交互。以下是相关数据结构的简化描述:

```c

typedef struct {

复制代码
int file\_descriptor;

uint32\_t file\_length;

void pages[TABLE\_MAX\_PAGES];

} Pager;

typedef struct {

复制代码
void pages[TABLE\_MAX\_PAGES];

Pager pager;

uint32\_t num\_rows;

} Table;

```

pager抽象层设计 :pager提供了一个访问页缓存的接口,其中同时具备缓存命中与未命中处理逻辑。

  1. 代码实现细节
3.1 ◆ 打开和关闭数据库

打开数据库时,我们需要创建 Pager 对象,并初始化数据结构。我们重命名了new_table()函数为db_open(),以更清晰地反映其功能。打开连接的过程包括:打开数据库文件、初始化pager数据结构以及初始化table数据结构。以下是简化后的new_table()函数实现:

```c

Tabledb_open(const char filename) {

复制代码
Pager pager = pager\_open(filename);

uint32\_t num\_rows = pager->file\_length / ROW\_SIZE;

// ... 其他必要的初始化步骤 ...

}

```

页缓存刷新机制 :在关闭数据库时,需将页缓存刷新到磁盘,以保证数据持久性。这包括写回缓存到磁盘,然后关闭文件,最后释放相关资源。

3.2 ◆ 执行关闭数据库及代码逻辑

测试案例:在这些测试中,我们将提供一个数据库文件名,然后尝试执行几个数据库命令,例如选择操作,并在关闭连接后,验证数据仍然存在。

db_close()方法会在用户退出时执行以下操作:刷新页缓存到磁盘、关闭数据文件以及释放Pager和table数据结构的内存。

关闭数据库的逻辑

  • 执行关闭命令(如".exit")。

  • 刷新缓存到磁盘,以确保所有数据被保存。

  • 关闭数据库文件。

  • 释放所有的资源。

  1. 数据库测试及关闭
4.1 ◆ 测试案例

为了验证持久化实现后数据在关闭连接后仍可保留,我们将执行一系列测试。首先,使用终端模拟数据库操作:

执行以下命令:

```bash

./db mydb.db

```

数据库操作执行完毕后,再次执行相同命令,验证数据的一致性。

4.2 ◆ 关闭数据库及代码逻辑

在我们的实现中,关闭数据库连接的过程不仅会执行关闭命令,还会处理缓存刷新、文件关闭以及资源释放等操作。这将确保断电或系统崩溃时,数据库的完整性得到保护。

在上述代码中,我们处理了数据库文件的关闭逻辑,并引入了do\_meta\_command函数,该函数允许我们通过输入命令来执行必要的数据库关闭和清理操作。

相关推荐
二哈赛车手5 小时前
新人笔记---ApiFox的一些常见使用出错
java·笔记·spring
栗子~~5 小时前
JAVA - 二层缓存设计(本地缓冲+redis缓冲+广播所有本地缓冲失效) demo
java·redis·缓存
YDS8295 小时前
DeepSeek RAG&MCP + Agent智能体项目 —— RAG知识库的搭建和接口实现
java·ai·springboot·agent·rag·deepseek
星星也在雾里6 小时前
PgBouncer 解决 PostgreSQL 连接数超限 + 可视化监控
数据库·postgresql
未若君雅裁7 小时前
MyBatis 一级缓存、二级缓存与清理机制
java·缓存·mybatis
AI人工智能+电脑小能手7 小时前
【大白话说Java面试题 第65题】【JVM篇】第25题:谈谈对 OOM 的认识
java·开发语言·jvm
阿维的博客日记8 小时前
Nacos 为什么能让配置动态生效?(涉及 @RefreshScope 注解)
java·spring
雨辰AI8 小时前
SpringBoot3 + 人大金仓读写分离 + 分库分表 + 集群高可用 全栈实战
java·数据库·mysql·政务
长城20248 小时前
关于MySql的ONLY_FULL_GROUP_BY问题
数据库·mysql·聚合列
常常有8 小时前
MySQL 底层执行原理:输入SQL语句到两阶段提交
数据库·sql·mysql