写在前面
本文是数据库系列的第一篇。这个系列计划写 10 篇,主线是横向对比 Oracle、SQL Server、MySQL、PostgreSQL 四大关系数据库的底层原理,并在最后跳出来俯瞰整个数据存储生态(OLAP / 数仓 / Lakehouse)。
开篇不深入任何单一原理,目标是建立一张"原理地图"——用一行 UPDATE 语句把整本系列的 10 个主题串起来,让你看后面每一篇时都知道它处在地图的哪一格。
一、从一行 UPDATE 说起
考虑这条最普通的 SQL:
1
|
UPDATE accounts SET balance = balance - 100 WHERE id = 42;
|
在你按下回车到返回"1 row affected"之间,数据库内部发生的事情远比你想象的多:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
1. 连接层: 校验会话、权限、参数绑定
2. 解析器: 词法/语法分析,生成 AST
3. 优化器: 决定走哪个索引、用什么 JOIN 顺序
4. 执行器: 按"打开表 → 定位行 → 改字段"的步骤执行
5. 事务层: 写 Undo Log(保证可回滚)+ 写 Redo Log(保证持久)
6. 缓冲池: 修改的是内存中的页,并不立即落盘
7. 锁系统: 对 id=42 这行加 X 锁,避免其他事务改
8. MVCC: 旧版本写入 Undo 链,让并发读不会看到新值
9. 提交: Redo Log fsync 到磁盘,事务正式可见
10. 复制: Redo/WAL 流式推送给从库(如果是主从架构)
后续:
- 后台 Checkpoint 把脏页刷盘
- 崩溃重启时用 Redo 重放、Undo 回滚
- Binlog 也会被消费同步到下游(订阅 / 数仓)
|
这一行 SQL 牵出了 10 个原理子系统,正是本系列要逐个深挖的:
| 步骤 |
涉及子系统 |
本系列对应篇 |
| 4-5 |
存储引擎(数据怎么放、页怎么组织) |
第 2 篇 |
| 3,4 |
索引(怎么定位 id=42 这行) |
第 3 篇 |
| 5,9 |
事务 ACID(原子性 + 持久性) |
第 4 篇 |
| 8 |
MVCC 与隔离级别 |
第 5 篇 |
| 7 |
锁与并发控制 |
第 6 篇 |
| 5,9 |
日志与崩溃恢复 |
第 7 篇 |
| 10 |
复制与高可用 |
第 8 篇 |
| 2,3 |
SQL 方言与查询优化器 |
第 9 篇 |
| —— |
数据存储全景(OLAP/数仓/Lakehouse) |
第 10 篇 |
读完这 10 篇,再回头看这行 UPDATE,你应当能说清每一步在四大数据库里叫什么名字、走什么代码路径、踩到哪些坑。
二、四大关系数据库的身世
2.1 Oracle:商业数据库的标杆
1
2
3
4
5
|
出身:1979 年由 Larry Ellison 创立,关系数据库商业化的先驱
版本:Oracle 7 → 8i → 9i → 10g → 11g → 12c → 18c → 19c → 21c → 23ai
定位:企业级核心交易系统、大型 OLTP、数据仓库
关键词:SGA/PGA、RAC(共享存储集群)、Data Guard、ASM、Exadata 一体机
许可证:商业,按 CPU 插槽计费,昂贵
|
2.2 SQL Server:微软生态的深度集成
1
2
3
4
5
|
出身:1989 年微软与 Sybase 合作开发,后独立分叉
版本:6.5 → 7.0 → 2000 → 2005 → ... → 2019 → 2022
定位:Windows 生态首选、企业 OLTP、近年也做 Linux + 容器
关键词:T-SQL、SQLOS、AlwaysOn、MSDTC、Columnstore、SSIS/SSAS/SSRS
许可证:商业,按 Core 计费,Express 免费但有限制
|
2.3 MySQL:互联网公司的最爱
1
2
3
4
5
6
|
出身:1995 年瑞典 MySQL AB 公司,2008 被 Sun 收购,2010 被 Oracle 收购
版本:3.x → 4.x → 5.x → 8.0 → 8.4 → 9.x(创新版)
分支:MariaDB(MySQL 创始人 fork)、Percona Server(性能版)
定位:互联网 OLTP、Web 应用、电商
关键词:InnoDB(默认引擎)、Binlog、MGR(Group Replication)、半同步复制
许可证:GPL + 商业双授权
|
2.4 PostgreSQL:最像 Oracle 的开源数据库
1
2
3
4
5
|
出身:1996 年从 Berkeley 的 POSTGRES 项目演化而来,2010 后社区爆发
版本:9.x → 10 → 11 → ... → 17
定位:复杂查询、地理数据(PostGIS)、JSON、扩展生态
关键词:进程模型、WAL、流复制 + 逻辑复制、丰富的索引类型、扩展(Extension)
许可证:PostgreSQL License(BSD-like),完全开源
|
2.5 四家定位坐标
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
OLAP 能力 ↑
│
Oracle ───────┼──────── PostgreSQL
│
SQL Server │
│
──────────────────┼────────────── 成熟度 →
│
MySQL │
│
OLTP 能力 ↑(其实是同一轴)
不同象限的擅长领域:
- Oracle/SQL Server:金融核心、ERP、关键交易系统
- MySQL:互联网高并发 OLTP
- PostgreSQL:复杂分析、地理数据、JSON 存储
|
三、进程/线程模型对比
四大数据库的"骨架"——也就是它们如何组织进程/线程——差异巨大。这个差异决定了内存架构、连接方式、并发性能的根本走向。
3.1 Oracle:多进程 + 共享内存(SGA)
1
2
3
4
5
6
7
8
9
10
11
12
|
一个 Oracle 实例由多个进程组成,进程间通过共享内存段(SGA)通信:
┌──────────────────────────────────────┐
│ SGA(共享内存) │
│ Buffer Cache / Redo Buffer / │
│ Shared Pool / Large Pool / Java Pool│
└────┬──────┬──────┬──────┬──────┬─────┘
│ │ │ │ │
PMON SMON DBWn LGWR CKPT ...(后台进程)
▲
│
Server Process(每个会话一个,或共享)
|
1
2
3
4
5
6
|
特点:
- 后台进程分工:DBWn 写脏页、LGWR 写 Redo、SMON 系统监控、PMON 进程监控
- 两种连接模式:
* Dedicated Server:每个会话一个 server 进程(默认)
* Shared Server:通过 dispatcher 共享,适合大量短连接
- 进程间通过共享内存(SGA)高效通信,无 IPC 开销
|
3.2 SQL Server:单进程多线程(SQLOS)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
SQL Server 是一个进程,里面跑数千个线程,由 SQLOS(调度器)管理:
┌──────────────────────────────────────┐
│ sqlservr.exe(单进程) │
│ ┌─────────────────────────────┐ │
│ │ SQLOS │ │
│ │ Scheduler(每 CPU 一个) │ │
│ └────────┬────────┬────────┬───┘ │
│ │ │ │ │
│ Worker Worker Worker │
│ (线程) (线程) (线程) │
└──────────────────────────────────────┘
│
Buffer Pool(用户态内存)
|
1
2
3
4
5
6
|
特点:
- 单进程多线程,所有连接共用一个进程
- SQLOS:自研的用户态调度器,避免 OS 上下文切换
- 每个 CPU 一个 Scheduler,Worker 跑在上面
- 内存:Buffer Pool 是用户态分配,不需要共享内存段
- 线程切换比进程切换便宜,适合极高并发
|
3.3 MySQL:多线程(每个连接一个线程)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
MySQL 服务器进程是单进程多线程,类似 SQL Server:
┌──────────────────────────────────────┐
│ mysqld(单进程) │
│ ┌────────────────────┐ │
│ │ Server Layer │ │
│ │ (解析/优化/执行) │ │
│ └─────────┬──────────┘ │
│ │ │
│ ┌─────┴───────┐ │
│ ▼ ▼ │
│ InnoDB 其他引擎 │
│ (独立线程池) │
└──────────────────────────────────────┘
线程类型:
- connection thread:每个客户端连接一个
- innodb master thread:刷盘、合并
- purge thread:清理 Undo
- page cleaner thread:刷脏页
- IO thread:AIO 读写
|
1
2
3
4
5
|
特点:
- Server Layer + Storage Engine 双层架构(引擎可插拔)
- 默认每个连接一个线程(thread-per-connection)
- 5.5+ 支持 thread pool(企业版 / Percona / MariaDB)
- InnoDB 内部有独立的线程池负责后台任务
|
3.4 PostgreSQL:多进程(每个连接一个进程)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
PostgreSQL 是最传统的"多进程"架构:
┌──────────────────────────────────────┐
│ postmaster(主进程) │
│ fork │
│ ├── backend(连接 1) │
│ ├── backend(连接 2) │
│ └── backend(连接 3) │
│ │
│ + 后台进程: │
│ checkpointer、bgwriter、walwriter │
│ autovacuum、stats collector │
└──────────────────────────────────────┘
│
Shared Buffers(共享内存段,System V / POSIX shm)
|
1
2
3
4
5
6
7
|
特点:
- 每个连接 fork 一个 backend 进程(进程模型)
- 进程间通过共享内存通信(Shared Buffers)
- 类似 Oracle,但更"原始":没有 dispatcher 模式
- 优点:进程隔离好,崩溃不影响其他连接
- 缺点:进程比线程重,大量连接时内存开销大
- 连接池方案:pgbouncer / pgcat(在客户端和数据库之间)
|
3.5 横向对比表
| 维度 |
Oracle |
SQL Server |
MySQL |
PostgreSQL |
| 进程/线程 |
多进程 |
多线程(SQLOS) |
多线程 |
多进程 |
| 共享内存 |
SGA |
Buffer Pool(用户态) |
Buffer Pool(用户态) |
Shared Buffers |
| 连接模型 |
Dedicated/Shared |
Thread pool |
Thread-per-conn |
Process-per-conn |
| 后台任务 |
DBWn/LGWR/SMON |
后台线程 |
Master/Purge/Cleaner |
bgwriter/walwriter |
| 大量连接方案 |
Shared Server |
默认就支持 |
企业版线程池 |
pgbouncer |
1
2
3
4
|
关键差异:
- Oracle/PG:操作系统级进程,崩溃影响小但开销大
- MSSQL/MySQL:用户态线程,开销小但单线程 bug 会拖垮整个实例
- PG 是四家里连接模型最"重"的,所以 pgbouncer 几乎是生产标配
|
四、整体架构
抛开进程/线程细节,关系数据库的逻辑架构大体是相似的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
┌──────────────────────────────────────┐
│ 客户端 / Driver │
└─────────────────┬────────────────────┘
│ SQL(TDS/MySQL/Wire/Net8 协议)
▼
┌──────────────────────────────────────┐
│ 连接层 │
│ 鉴权 / 会话 / 进程或线程分配 │
└─────────────────┬────────────────────┘
▼
┌──────────────────────────────────────┐
│ 解析器 Parser │
│ SQL 文本 → AST 语法树 │
└─────────────────┬────────────────────┘
▼
┌──────────────────────────────────────┐
│ 优化器 Optimizer │
│ AST → 执行计划(RBO / CBO) │
└─────────────────┬────────────────────┘
▼
┌──────────────────────────────────────┐
│ 执行器 Executor │
│ 算子:Scan/Filter/Join/Agg/Sort │
└─────────────────┬────────────────────┘
▼
┌──────────────────────────────────────┐
│ 存储引擎 Storage Engine │
│ 页/块读写、缓冲池、索引、事务、日志 │
└─────────────────┬────────────────────┘
▼
磁盘 / SSD
|
4.1 MySQL 的特殊之处:可插拔存储引擎
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
Server Layer(解析/优化/执行)和 Storage Engine 是分离的:
Server Layer
├── InnoDB ← 默认,事务、行锁、MVCC
├── MyISAM ← 老引擎,表锁,已不推荐
├── Memory ← 内存表
├── Archive ← 压缩归档
├── NDB ← 集群(MySQL Cluster)
└── 第三方:RocksDB、TokuDB、TiDB(兼容协议)
其他三家:
- Oracle:可换段类型(heap / index-organized / partitioned),但引擎统一
- SQL Server:可换页压缩、列存索引,但引擎统一
- PostgreSQL:12+ 有 Table Access Method 抽象,目前主要是 heap
|
MySQL 这种设计的好处和代价:
- 好处:可以针对场景选引擎(OLTP 用 InnoDB,归档用 Archive)
- 代价:跨引擎功能不统一(MyISAM 不支持事务、InnoDB 才有外键等)
4.2 解析器与优化器
| 数据库 |
解析器 |
优化器 |
执行器 |
| Oracle |
自研 |
CBO + RBO |
Row-based + Vectorized(12c+) |
| SQL Server |
自研 |
CBO(Cost-Based) |
Row + Batch mode |
| MySQL |
自研(8.0+ 重大重写) |
CBO(5.7+ 完善) |
Iterator + Volcano |
| PostgreSQL |
自研(基于 flex/bison) |
CBO + Genetic(GEQO) |
Volcano model |
后续第 9 篇会深入展开优化器对比,这里先建立"解析器 → 优化器 → 执行器"的概念骨架。
五、本系列 10 篇要解决的 10 个问题
把 10 篇的目标用一句话讲清楚:
| 篇 |
主题 |
一句话问题 |
| 1(本篇) |
开篇总览 |
关系数据库内部到底有几个子系统? |
| 2 |
存储引擎 |
一行数据在磁盘上长什么样?为什么 MySQL 主键就是数据? |
| 3 |
索引原理 |
为什么几乎所有索引都是 B+ 树?PG 的 GIN/GiST 又是什么? |
| 4 |
事务 ACID |
原子性怎么实现?Durability 怎么保证?分布式事务怎么落? |
| 5 |
MVCC 与隔离级别 |
为什么读不阻塞写?为什么 PostgreSQL 表会膨胀? |
| 6 |
锁与并发控制 |
行锁怎么实现?SQL Server 为什么会锁升级?死锁怎么破? |
| 7 |
日志与崩溃恢复 |
Redo、Undo、Binlog、WAL 这么多日志都是干嘛的? |
| 8 |
复制与高可用 |
主从怎么同步?脑裂怎么防?RAC、MGR、AlwaysON 各是什么? |
| 9 |
SQL 方言与优化器 |
同样的 SQL 为什么在 PG 比 MySQL 快 10 倍? |
| 10 |
数据存储全景 |
OLTP、OLAP、HTAP、数仓、Lakehouse 怎么选? |
每篇都会包含三个层次:
- 原理:核心机制 + 算法 + 数据结构
- 对比:四家差异 + 命名对照 + 优劣
- 实战:执行计划、配置参数、踩坑案例
六、核心术语对照表
四大数据库的术语往往表达同一个概念,但叫法完全不同。这张表是后续阅读的"翻译字典"。
6.1 内存相关
| 概念 |
Oracle |
SQL Server |
MySQL (InnoDB) |
PostgreSQL |
| 数据缓存 |
Buffer Cache |
Buffer Pool |
Buffer Pool |
Shared Buffers |
| 日志缓存 |
Redo Log Buffer |
Log Cache |
Redo Log Buffer |
WAL Buffers |
| 共享内存区 |
SGA |
——(用户态分配) |
——(用户态分配) |
Shared Memory |
| 私有内存 |
PGA |
—— |
Thread stack |
Process Mem |
| SQL/计划缓存 |
Shared Pool (Library Cache) |
Plan Cache |
Query Cache(已废弃) |
plpgsql cache |
6.2 后台任务
| 任务 |
Oracle |
SQL Server |
MySQL |
PostgreSQL |
| 写脏页 |
DBWn |
Checkpoint/Lazy Writer |
Page Cleaner |
bgwriter / checkpointer |
| 写日志 |
LGWR |
Log Writer |
Log Manager |
walwriter |
| 清理旧版本 |
SMON(Undo 表空间) |
——(tempdb 清理) |
Purge Thread |
autovacuum |
| 统计信息收集 |
自动(GATHER_STATS_JOB) |
自动 |
自动(默认开启) |
autovacuum 分析 |
6.3 日志类型
| 用途 |
Oracle |
SQL Server |
MySQL |
PostgreSQL |
| Redo(重做) |
Redo Log |
Transaction Log |
Redo Log(ib_logfile) |
WAL |
| Undo(回滚) |
Undo 表空间 |
Transaction Log(同一份) |
Undo Log(undo tablespace) |
Old tuple in heap |
| 归档 |
Archive Log |
——(备份 log backup) |
Binlog |
WAL archive |
| 主从复制 |
Redo + Archive |
Transaction Log |
Binlog |
WAL stream |
1
2
3
4
5
|
关键观察:
- Oracle / PG 把 Redo 和 Undo 完全分离
- SQL Server 在同一个 Transaction Log 里同时承担 Redo/Undo
- MySQL InnoDB 同时有 Redo Log 和 Undo Log,再加上 Binlog
- 复制日志:MySQL 用 Binlog,其他三家直接用 Redo/WAL/Transaction Log
|
6.4 索引术语
| 概念 |
Oracle |
SQL Server |
MySQL (InnoDB) |
PostgreSQL |
| 主键索引 |
IOT / 普通索引 |
Clustered Index |
Clustered Index(=数据) |
普通索引(堆表) |
| 二级索引 |
Normal Index |
Nonclustered Index |
Secondary Index |
Index |
| 唯一索引 |
Unique Index |
Unique Index |
Unique Index |
Unique Index |
| 联合索引 |
Composite |
Composite |
Composite |
Composite |
| 函数索引 |
Function-based |
Computed Column |
Functional(5.7+) |
Expression Index |
| 位图索引 |
Bitmap |
——(仅 DW 用) |
—— |
—— |
| 倒排索引 |
—— |
—— |
—— |
GIN |
| 部分索引 |
—— |
Filtered |
—— |
Partial Index |
后续第 3 篇会展开。
七、选型哲学
讲完架构,最后聊点选型。每家数据库都有它最舒服的场景,没有"银弹"。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
Oracle 适合:
- 核心金融、ERP,对一致性要求极高
- 预算充足、需要商业支持
- 需要 RAC 共享存储集群(单库扩展到多节点)
SQL Server 适合:
- 已是 Windows + .NET 生态
- 需要 BI 全家桶(SSIS/SSAS/SSRS)
- 内部团队熟悉 T-SQL
- 也适合 Linux 部署(2017+)
MySQL 适合:
- 互联网高并发 OLTP
- 数据规模可控(单库 TB 级以内)
- 团队熟悉 LAMP/LEMP 栈
- 需要多种存储引擎灵活搭配
PostgreSQL 适合:
- 复杂查询、分析型负载
- 需要 JSON / JSONB / GIS(PostGIS)
- 希望使用 BSD-like 许可证
- 想用 Oracle 但预算不够(PG 的语法/特性最像 Oracle)
|
7.1 一些常见的误区
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
误区 1:MySQL 比 PostgreSQL 慢
真相:纯单条 OLTP 写入,InnoDB 通常更快;复杂分析查询 PG 更快。
误区 2:Oracle 一定比开源好
真相:除非用 RAC / Exadata / 高级安全特性,PG/MySQL 8.x 能覆盖大部分场景。
误区 3:PostgreSQL 不能做高并发
真相:配合 pgbouncer + 多实例,PG 也能撑住极高并发;只是默认配置不如 MySQL。
误区 4:SQL Server 只能跑 Windows
真相:2017+ 官方支持 Linux + Docker,但生态工具仍以 Windows 为主。
误区 5:四大数据库的功能都差不多
真相:底层架构差异巨大——进程模型、日志、MVCC、复制、锁——这些都影响生产实践。
|
八、小结
本文作为开篇,主要做了三件事:
- 用一行 UPDATE 串联起本系列要讲的 10 个原理子系统
- 横向对比了四大数据库的身世、进程模型、整体架构
- 给出四方言核心术语对照表(内存、后台、日志、索引)
1
2
3
4
|
记住三句话:
1. 四大数据库解决的是同一组问题,但答案不同
2. 进程/线程模型是其他所有差异的根源
3. 同一个概念在四家里叫不同名字,建立"翻译字典"是基本功
|
下一篇将从"数据在磁盘上长什么样"开始,深入存储引擎的世界:页、块、Extent、Segment、堆表 vs 索引组织表,以及为什么 MySQL 的主键就是数据本身。