1. 为什么数据库需要自己的内存管理机制
在计算机系统中,内存管理通常被认为是操作系统的职责。操作系统通过虚拟内存、页表、缺页中断等机制,为应用程序提供了"看似无限内存"的抽象。然而,数据库系统却很少依赖这套机制,而是自行实现了一套完整的内存管理体系。这背后有三个关键原因:
首先是空间控制的需求。数据库系统需要精确掌握每个数据页在内存中的状态:是否被缓存、是否为脏页、是否正在被使用等。这些信息对事务处理、并发控制和恢复机制至关重要,但在操作系统的页缓存模型中是不可见的。
其次是时间局部性的控制。数据库系统希望将高频访问的"热点"数据长期保留在内存中,而将一次性访问的数据尽快淘汰。操作系统的页面替换策略(如LRU)无法区分这两种访问模式,往往会在全表扫描等操作中误伤真正重要的数据页。
最后也是最重要的是,数据库必须支持大于物理内存容量的数据集,但又不能像普通应用那样依赖操作系统的缺页中断来被动调页。一次不可控的缺页中断可能导致执行线程长时间阻塞,这对高并发的数据库系统来说是不可接受的。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Buffer Pool的核心设计
2.1 基本结构与工作原理
Buffer Pool是现代数据库系统中内存管理的核心抽象。它由一组固定大小的缓冲帧(Frame)组成,每个帧的大小通常与数据库页大小保持一致(如4KB、8KB或16KB)。这种设计避免了在内存和磁盘间传输数据时产生额外的拆分或拼接开销。
Buffer Pool采用回写(Write-Back)而非直写(Write-Through)策略。当事务修改页面内容时,修改首先只体现在内存中的缓冲帧里,页面被标记为"脏页",但不会立即同步到磁盘。只有在特定条件下(如页面被驱逐、检查点触发等),DBMS才会将脏页刷新到磁盘。
2.2 关键元数据管理
每个缓冲帧除了存储数据页内容外,还需要维护一组关键元数据:
- 脏位(Dirty Bit):标识页面自上次写回磁盘后是否被修改
- 固定计数(Pin Count):记录当前有多少线程正在使用该页面
- 访问时间戳:用于实现各种页面替换算法
这些元数据使得DBMS能够精确判断哪些页面可以安全地被替换,哪些必须继续驻留内存。
2.3 页表与快速查找
为了快速定位内存中的数据库页面,DBMS维护了一个页表(Page Table)。
