从文件系统到数据库:为什么我们需要数据库?

15 阅读4分钟

一、文件存储的局限

在数据库诞生之前,计算机存储数据的方式非常朴素——直接用文件。比如一个用户文件 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)

理解了这五个问题,就掌握了理解任何数据库的钥匙。