专业书籍精读 · Database Internals · 第 3 章

文件格式

Database Internals · Ch 3 · Alex Petrov · 2019

EN →

这一章讲什么?

你手机里的相册、微信的聊天记录、公司的订单库,最后都变成硬盘上的一个文件。上一章讲了数据库为什么用「目录树」来找数据,这一章往下钻一层:树的每个节点,落到硬盘上到底是怎么摆的一堆字节?听着像枯燥的收尾工作,其实所有漂亮算法能不能在真机器上跑起来,全看这一层。

先打个比方

把硬盘想成一本活页笔记本:它不许你「在第 37 行插一句话」,只能一整页撕下来、写好、再放回去。可数据库要塞进去的东西长短不一——一条订单 80 个字节,一段商品描述 3000 个字节。怎么把长短不齐的内容,整整齐齐塞进大小固定的页里,还得随时能加、能删?

旧世界为什么难

在内存里,这些脏活有人替你干:要放新东西,跟系统要块地方就行;东西不要了,还回去;想记住它在哪,记个门牌号即可。到了硬盘上,这三样便利全没了——门牌号换一页就作废,删掉一条留下的坑没人替你填,页的大小还是死的。要是老实按「每条记录固定占一格」来排,那格子必须按最长的记录来定,短记录就白白浪费一大半。

核心机制:一页纸 + 页首目录

数据库的解法,和排一张菜单差不多聪明:正文从页尾往前写,目录从页首往后排,中间留白。

另外每页还会附一个对账码:写的时候算一遍存着,读回来再算一遍,对不上就知道这页在硬盘上悄悄坏了。文件开头则写着一句暗号和版本号——将来格式改了,程序一看就知道该用哪套规矩读。

带来了什么

你能打开的几乎所有数据库文件都长这样:PostgreSQL 一页 8 KB、MySQL 16 KB、SQLite 4 KB,页里都是「页首目录 + 页尾正文」。代价也很诚实:删除并不立刻还你磁盘空间——空洞要等某次整理才收得回来,而那次整理得把整页重写一遍。

一句话记住

硬盘只认整页,记录却长短不一。数据库的答案是一页纸 + 页首目录:正文随便摆、目录管顺序;删了先记在「空地清单」上、攒多了再整理;每页附一个对账码,防它在硬盘上悄悄烂掉。

想看真实的字节布局、槽目录示意图和各家引擎的选择? → 切到精读版