大数跨境

深入了解 SQLite 存储

深入了解 SQLite 存储 索引目录
2026-01-15
0
导读:关注「索引目录」公众号,获取更多干货。本文探讨SQLite 的安全网,包括freelists、leaf pages、trunk pages和 journals 。

关注「索引目录」公众号,获取更多干货。

本文探讨SQLite 的安全网,包括freelistsleaf pagestrunk pages和 journals 。

为什么 SQLite 需要空闲列表

SQLite 从不立即将未使用的页面返回给操作系统。

一旦页面被分配给数据库文件,除非进行显式的收缩操作,否则它将一直保留在该文件中。

当行被删除、索引被删除或表被移除时,页面将变为活动状态

SQLite 不会丢弃这些页面,而是将它们放入一个名为freelist 的结构中。

freelist 只是 SQLite 内部未使用的页面清单,这些页面随时可以重新用于未来的插入操作,而不会增加文件大小。

什么是自由列表?

空闲列表是一个直接嵌入到数据库文件中的链接结构。



关键事实:

  • 一个空闲列表主干页码存储在文件头偏移量为32 的位置。
  • 剩余页数总数
    存储在偏移量 36 处。
  • 所有免费页面均被跟踪,无垃圾回收,无歧义。

SQLite 将空闲列表组织成一个有根的树状列表,从文件头开始向外分支。

树干页和叶子页(自由列表页)

自由列表页面分为两种子类型

主干页

主干页面是一个免费页面的目录。

其布局(从页面开头开始):

  1. 4 字节→下一主干页
    的页码(0如果没有页码则为 0)
  2. 4 字节
    → 此主干上存储的叶子指针的数量。
  3. N × 4 字节
    → 叶子页的页码

每个主干页面可以同时引用多个免费页面。

叶子页

叶子页面是指没有任何实际结构的自由页面。其内容未指定,可能包含先前使用留下的垃圾信息。

叶子页面才是真正可重用的页面。主干页面只是指向它们

页面如何进入和退出自由列表

当页面变为非活动状态时,SQLite会将其添加到空闲列表中。但页面实际上仍然保留在数据库文件中。

当需要写入新数据时:



这就解释了为什么数据库经常增长但不会自动缩小。

缩小数据库:VACUUM 和 Autovacuum

如果空闲列表过大,就会造成磁盘浪费。SQLite 提供了两种解决方案:

真空



这是一项难度很高但又非常精准的操作。

自动吸尘模式



自动清理功能以运行时开销为代价来换取空间清理。

SQLite 中的日志文件

日志文件是一种崩溃恢复文件,用于记录数据库更改,以便 SQLite 可以回滚未完成的事务。

它保证了原子性和持久性,确保数据库在发生故障后永远不会只写入一半。

SQLite 历来使用传统日志记录方式,其中包括:

  1. 回滚日志
  2. 声明日志
  3. 主日志

从 SQLite 3.7.0 开始,数据库要么使用传统日志记录,要么使用 WAL,绝不会同时使用两者。

内存数据库完全跳过日志记录,所有操作都在内存中完成。



回滚日志:SQLite 的安全带

每个数据库都有一个回滚日志文件

  • 存储在与数据库相同的目录中
  • -journal
    通过在数据库文件名后附加名称来命名
  • 在写入事务开始时创建
  • 交易完成后(默认情况下)删除

回滚日志存储数据库页面之前的图像,允许 SQLite 在出现问题时恢复数据库。

回滚日志结构

回滚日志被分为多个日志段



每个部分包含:

  1. 段头
  2. 一条或多条日志记录

大多数情况下,只有一个片段。多个片段只会在特殊情况下出现。

章节标题:第一道防线

每个段头都以八个魔数开头:

D9 D5 05 F9 20 A1 63 D7

这些字节仅用于完整性检查。



头部还存储着:

  • 日志记录数 (nRec)
  • 用于校验和计算的随机值
  • 原始数据库页数
  • 磁盘扇区大小
  • 数据库页面大小

头部始终占用一个磁盘扇区,所有值均以大端格式存储。

期刊保留模式

默认情况下,SQLite会在提交或回滚后删除日志文件。

您可以使用以下方法更改此设置:

  • DELETE
    (默认)
  • PERSIST
  • TRUNCATE

独占锁定模式下,日志文件会在事务之间保留,但其头部会在使用之间失效或被截断。

异步事务(不安全但速度快)

SQLite支持异步模式

  • 日志文件和数据库文件永远不会被刷新。
  • 更快捷的交易
  • nRec
    设置为-1
  • 恢复过程依赖于文件大小,而不是元数据

此模式不具备防崩溃功能,主要用于开发或测试场景,但确实可以提高性能。

为什么这一层很重要

深入到这一层面,SQLite 的理念才得以展现:

  • 空间是可以循环利用的,而不是被丢弃的。
  • 通过精确、最少的元数据实现安全性
  • 一切皆有明确规定,所有信息都会被追踪记录。
  • 恢复逻辑直接编码到文件结构中

关注「索引目录」公众号,获取更多干货。


【声明】内容源于网络
0
0
索引目录
索引目录是一家专注于医疗、技术开发、物联网应用等领域的创新型公司。我们致力于为客户提供高质量的服务和解决方案,推动技术与行业发展。
内容 444
粉丝 0
索引目录 索引目录是一家专注于医疗、技术开发、物联网应用等领域的创新型公司。我们致力于为客户提供高质量的服务和解决方案,推动技术与行业发展。
总阅读12
粉丝0
内容444