文章
数据库自底向上的抽象
理解数据库自底向上的抽象层次,可以帮助我们看清整个系统是如何从最基础的硬件构建到用户可交互的复杂功能的
目录
- 1. 物理硬件层 (Physical Hardware)
- 2. 操作系统层 (Operating System - OS)
- 3. 存储管理器层 (Storage Manager)
- 4. 数据结构与访问方法层 (Data Structures & Access Methods)
- 5. 关系代数/执行原语层 (Relational Algebra / Execution Primitives)
- 6. 事务与并发控制层 (Transaction & Concurrency Control)
- 7. 查询处理器层 (Query Processor)
- 8. 应用编程接口 (API) 与用户接口层 (User Interface)
- 📎 参考文章
理解数据库自底向上的抽象层次,可以帮助我们看清整个系统是如何从最基础的硬件构建到用户可交互的复杂功能的。这与自顶向下的工作流程分析是一个相反但互补的视角。 我们可以将数据库系统的抽象层次从最底层到最顶层大致分为以下几个主要层面:
1. 物理硬件层 (Physical Hardware)#
- 构成: 这是所有计算的基础。包括:
- 持久存储设备 (Persistent Storage): 机械硬盘 (HDD)、固态硬盘 (SSD)。这是数据最终存放的地方。
- 易失性存储 (Volatile Memory): 内存 (RAM)。用于临时存储数据和程序代码,速度远快于持久存储。
- 中央处理器 (CPU): 执行指令,进行计算和控制。
- 网络接口 (Network Interface): 用于与其他计算机通信。
- 抽象: 这一层几乎没有抽象,是物理实体。数据库系统最终依赖这些硬件来存储数据和执行操作。
2. 操作系统层 (Operating System - OS)#
- 构成: 运行在物理硬件之上的系统软件。
- 提供的抽象: OS 为上层软件(包括数据库)提供了关键的抽象和管理功能,屏蔽了直接操作硬件的复杂性:
- 设备驱动 (Device Drivers): 允许数据库以统一的方式与不同类型的存储设备交互。
- 文件系统 (File System): 将磁盘组织成文件和目录的结构。数据库通常将其数据存储在 OS 文件中(尽管有些高性能数据库会使用原始磁盘分区以绕过文件系统缓存和开销)。OS 负责将文件读写请求转换为对磁盘块的实际操作。
- 内存管理 (Memory Management): 管理物理内存的分配和回收,提供虚拟内存机制,允许数据库使用比物理内存更大的地址空间。
- 进程/线程管理 (Process/Thread Management): 允许数据库作为多个进程或线程并发执行,处理多个用户请求。
- 网络栈 (Networking Stack - e.g., TCP/IP): 提供网络通信的基础,使数据库能接收客户端连接并传输数据。
- 数据库如何使用: 数据库通过 OS 提供的系统调用来请求服务,如打开/关闭文件、读/写文件内容、分配内存、创建网络连接等。
3. 存储管理器层 (Storage Manager)#
这是数据库管理系统 (DBMS) 内部处理数据存储和检索的最底层。它构建在 OS 文件系统(或裸设备)之上。
- 构成: 包含多个子组件,负责数据的物理组织和 I/O。
- 提供的抽象:
- 磁盘空间管理器 (Disk Space Manager):
- 在数据库文件内部管理磁盘空间的分配和回收(例如,以区段 Extent 或页 Page 为单位)。
- 跟踪空闲空间,处理文件扩展。
- 抽象掉: OS 文件内具体字节的布局。
- 页面/块管理器 (Page/Block Manager):
- 将数据库文件视为一个由固定大小的数据页 (Data Pages) 或数据块 (Data Blocks)(通常为 4KB, 8KB, 16KB)组成的集合。这是数据库进行磁盘 I/O 的基本单位。
- 负责将页号(逻辑地址)映射到文件内的物理偏移量。
- 抽象掉: 磁盘扇区和具体文件偏移量。
- 缓冲管理器 (Buffer Manager / Buffer Pool Manager):
- 在主内存 (RAM) 中维护一个缓冲池 (Buffer Pool),用于缓存从磁盘读取的数据页。
- 当需要访问某个数据页时,首先检查它是否在缓冲池中。如果在(缓存命中),则直接从内存访问;如果不在(缓存未命中),则从磁盘读取到缓冲池(可能需要根据替换算法如 LRU 逐出一个旧页),然后再访问。
- 管理“脏页”(在内存中被修改但尚未写回磁盘的页)的回写。
- 抽象掉: 实际的磁盘读写操作,为上层提供了一个看起来像是在内存中访问数据页的接口。
- 磁盘空间管理器 (Disk Space Manager):
- 数据库如何使用: 上层组件通过请求特定的数据页与缓冲管理器交互,而不是直接进行文件 I/O。
4. 数据结构与访问方法层 (Data Structures & Access Methods)#
这一层在存储管理器提供的“数据页”抽象之上,构建了更高级的数据组织和访问机制。
- 构成:
- 记录/行格式 (Record/Row Format): 定义了如何在数据页内组织单个数据记录(行),包括字段的存储、变长字段的处理、空值表示等(例如,Slotted Page 结构)。
- 索引结构 (Index Structures): 如 B+树 (B+ Trees)、哈希索引 (Hash Indexes)、R树 (R-Trees) 等。这些结构(本身也存储在数据页中)允许根据特定的键值快速定位到包含相应记录的数据页和记录位置。
- 堆文件/表结构 (Heap File/Table Organization): 无序存储记录集合的方式(通常记录插入到任何有空间的页)。
- 元数据/系统目录 (Metadata/System Catalog): 存储关于数据库模式(表、列、索引、视图、用户、权限等)的信息,这些信息本身也使用上述数据结构存储。
- 提供的抽象:
- 记录/行: 将数据页内的字节序列抽象成结构化的数据记录。
- 键值查找: 通过索引,将“给我键值为 X 的记录”这样的请求快速映射到具体的记录。
- 表: 将一组相关的记录组织成一个逻辑上的表。
- 抽象掉: 数据页内部的字节布局、索引树的节点遍历细节。
- 数据库如何使用: 查询执行器通过这些访问方法来检索、插入、更新或删除记录。
5. 关系代数/执行原语层 (Relational Algebra / Execution Primitives)#
这一层实现了关系模型中的基本操作,作为查询执行的基础构建块。
- 构成: 一系列标准化的数据操作算法。
- 扫描 (Scan): 全表扫描、索引扫描。
- 选择/过滤 (Selection/Filter): 根据条件筛选记录。
- 投影 (Projection): 选择记录中的特定列。
- 连接 (Join): 如嵌套循环连接、哈希连接、合并连接。
- 排序 (Sort)。
- 聚合 (Aggregation): 如
SUM,COUNT,AVG。 - 分组 (Group By)。
- 提供的抽象:
- 将复杂的查询分解为一系列可在表或中间结果上执行的基本操作。
- 抽象掉: 底层数据结构(如 B+树)的具体操作细节,提供面向集合的操作。
- 数据库如何使用: 查询优化器生成的执行计划就是由这些原语组成的树状结构,查询执行器按计划调用这些原语来处理数据。
6. 事务与并发控制层 (Transaction & Concurrency Control)#
这一层确保数据库操作的 ACID 属性(原子性、一致性、隔离性、持久性),即使在多用户并发访问和系统故障的情况下也能保证数据的正确性。
- 构成:
- 事务管理器 (Transaction Manager): 跟踪事务的开始、提交、回滚状态。
- 锁管理器 (Lock Manager) 或 多版本并发控制器 (MVCC): 实现隔离性,防止并发事务相互干扰。锁管理器使用各种锁(行锁、页锁、表锁,共享锁、排他锁)来协调访问;MVCC 则通过为数据维护多个版本来避免读写冲突。
- 日志管理器 (Log Manager): 实现预写日志 (Write-Ahead Logging - WAL)。所有数据修改操作(对数据页的更改)都会先记录到持久的事务日志中,然后再修改缓冲池中的数据页。这保证了原子性和持久性。
- 恢复管理器 (Recovery Manager): 在系统崩溃后启动时,使用事务日志来将数据库恢复到一个一致的状态(重做已提交的事务,撤销未提交的事务)。
- 提供的抽象:
- 事务: 将一系列操作打包成一个原子单元,要么全部成功,要么全部失败。
- 隔离的执行环境: 每个事务感觉就像是独立在系统中运行一样。
- 持久的存储: 一旦事务提交,其结果就不会丢失。
- 抽象掉: 底层的并发冲突细节、日志记录的复杂性、崩溃恢复的过程。
- 数据库如何使用: 查询执行的每一步,尤其是数据修改操作,都会与事务和并发控制组件交互,以获取锁、记录日志等。
7. 查询处理器层 (Query Processor)#
这一层负责接收用户的查询请求(通常是 SQL),将其转换为高效的执行计划,并协调执行。
- 构成:
- 解析器 (Parser): 对 SQL 语句进行词法分析和语法分析,生成解析树。
- 验证器/绑定器 (Validator/Binder): 检查语义正确性(表、列是否存在,数据类型是否匹配,用户权限等),并将名称绑定到具体的数据库对象。
- 查询优化器 (Query Optimizer): 将解析和验证后的查询(通常是逻辑查询计划)转换为一个高效的物理执行计划。它会考虑多种执行策略(如使用哪个索引、哪种连接算法),并使用统计信息估算成本,选择成本最低的方案。
- 查询执行器 (Query Executor): 接收优化器生成的执行计划,并调用关系代数原语层提供的操作来实际执行查询,与事务层和存储引擎交互获取和修改数据。
- 提供的抽象:
- 声明式查询语言 (SQL): 用户只需说明“想要什么数据”,而无需关心“如何获取数据”。
- 高效的查询执行: 自动找到执行查询的较好方式。
- 抽象掉: 底层执行原语的组合方式、成本估算细节。
- 数据库如何使用: 这是用户与之交互的主要逻辑层面。
8. 应用编程接口 (API) 与用户接口层 (User Interface)#
这是数据库系统最顶层的抽象,提供给外部应用程序和最终用户。
- 构成:
- SQL 接口: 允许用户直接执行 SQL 语句。
- 客户端库/驱动程序 (Client Libraries/Drivers): 如 JDBC (Java), ODBC (C/C++), Python DB-API 等。这些库封装了网络通信协议和数据库交互细节,使应用程序能方便地连接数据库、发送查询、接收结果。
- 存储过程/函数/触发器: 允许在数据库服务器端定义和执行更复杂的逻辑。
- 命令行工具 (Command-Line Interface - CLI): 如
psql,mysql。 - 图形用户界面工具 (Graphical User Interface - GUI): 如 pgAdmin, DBeaver, MySQL Workbench。
- 提供的抽象:
- 一个与数据库交互的便捷途径,隐藏了所有底层的复杂性。
- 抽象掉: 网络连接细节、数据传输格式、会话管理等。 通过这些从硬件到用户接口的层层抽象,数据库系统得以将极其复杂的物理操作逐步封装成易于理解和使用的高级功能,同时保证了数据的可靠性、一致性和高效访问。每一层都依赖于其下层提供的服务,并为其上层提供更高级的功能。