一、文件存储的局限
在数据库诞生之前,计算机存储数据的方式非常朴素——直接用文件。比如一个用户文件 users.txt,内容长这样:
1,张三,20
2,李四,25
3,王五,30
程序处理数据的流程也很简单:打开文件、扫描全部内容、找到目标数据、修改、保存。对于几十条、几百条数据,这种方式完全够用。但随着数据量增长,问题开始一一浮现。
二、索引的快速查找
假设你有 10 亿用户,数据存储在一个文件中。要查找 id=900000000 的记录,最朴素的方式是从头到尾逐行扫描,时间复杂度为 O(N) ——最坏情况下需要读取 10 亿条数据。显然,这种"大海捞针"的方式在规模面前不堪一击。
于是,索引应运而生。索引的核心思想是"以空间换时间":不再每次都去原始数据中盲目搜索,而是提前构建一个快速查询结构。例如,原始数据按地址存储:1000 位置存 张三,2000 位置存 李四。索引则建立"名字→地址"的映射,查询时先查索引定位地址,再直接读取数据。
现代数据库中的 B+Tree、Hash Index、Bitmap Index、LSM Index 等,本质上都是为了降低数据查找的成本。这是数据库的第一次革命。
三、存储引擎的职责
早期的数据量不过几 MB,而内存有数 GB,全部载入内存毫无压力。但如今的数据库动辄达到 TB 甚至 PB 级别,不可能全部加载到内存中。这就引出了新的难题:哪些数据放在内存?哪些放在磁盘?何时加载?何时释放?
为了解决这些问题,存储引擎(Storage Engine) 诞生了。它负责数据的持久化存储、内存与磁盘之间的调度、缓存管理等一系列底层工作,是数据库最核心的组件之一。
四、事务的ACID保证
假设你的银行账户余额是 1000 元,执行扣款 100 元的操作。如果在修改过程中服务器突然断电,可能出现数据只改了一半的情况——余额变成了 900 元,但操作日志却没有记录。这种"半吊子"状态会导致严重的数据不一致。
因此,数据库需要 事务系统 来保证操作的可靠性。事务遵循著名的 ACID 原则:
- 原子性(Atomicity) :操作要么全部成功(余额变为 900),要么全部失败(余额保持 1000),不存在中间状态。
- 一致性(Consistency) :数据必须始终满足预设规则,比如余额不能为负数。
- 隔离性(Isolation) :多个用户同时操作,彼此之间互不干扰。
- 持久性(Durability) :一旦事务提交,即使断电,数据也不会丢失。
五、并发控制的必要性
互联网数据库从来不是单人在使用。以电商为例,用户 A 和用户 B 同时购买同一件商品,数据库必须妥善处理这种并发场景,避免超卖或数据混乱。为此,数据库发展出了多种并发控制机制:锁(Lock)、多版本并发控制(MVCC)、时间戳排序(Timestamp)、乐观并发控制等。
六、数据库的四大类
面对不同的业务需求,数据库逐渐分化出几大种类:
1. 关系型数据库(RDBMS)
代表:Oracle、MySQL、PostgreSQL。
核心目标是管理结构化业务数据,以表(Table)、行(Row)、列(Column)组织数据,支持 SQL 查询和完整的事务。适用于金融、电商、ERP 等企业级系统。
2. 嵌入式数据库
代表:SQLite。
目标是在应用程序内部提供数据库能力,无需独立服务器进程,直接以文件形式存储。广泛应用于手机、浏览器、物联网设备等场景。
3. KV 数据库
代表:Redis、RocksDB。
采用极简的 Key-Value 模型,追求极致的读写性能。常用于缓存、日志、高频写入等场景。
4. 分析型数据库
代表:ClickHouse、DuckDB。
专为海量数据分析而设计,擅长处理"过去五年销售趋势"这类统计查询。核心特点是列式存储、SIMD 加速和数据压缩。
七、总结
如果把所有数据库抽象来看,它们本质上都在回答五个问题:
| 问题 | 对应技术 |
|---|---|
| 数据如何存储? | 存储引擎(Storage Engine) |
| 数据如何查找? | 索引(Index) |
| 数据如何安全修改? | 事务(Transaction) |
| 多人如何同时修改? | 并发控制(Concurrency Control) |
| 如何应对海量规模? | 分布式系统(Distributed System) |
理解了这五个问题,就掌握了理解任何数据库的钥匙。