SICI · 天机门 · 第二十章

数据库系统基础 · 元婴四层

你以为一致性是免费的。隔离级别调高就调高,加锁就加锁,崩溃重做就行——可每一次"以为免费"的代价,不一致之雾都给你记着账。

不一致之雾低语:「隔离不需要代价?赌一局。你的账,我记着。」
序章

雾锁数据之门

五样东西,哪一样不需要数据库?

数据筑基殿的门楣上刻着一行字:"数据不灭,并发不乱。"门内悬浮着五道剪影——银行、电商、航班、社交、物流——在灰雾中半透明地晃动。诺依曼老祖背着手站在一旁。

数据库之渊,关系型数据库
诺依曼老祖 诺依曼老祖

「这是数据库。它管三件事:数据不丢、并发不乱、状态一致。你猜,这五样东西里,哪一样其实不需要它?」

不一致之雾 不一致之雾

「这五样东西,哪一样其实不需要数据库?猜错一笔,我记一笔。账记满了,到 S9 一起算。」

数据库依赖预测挑战器

反直觉下注(五选一)→ 每点一次露出底层并发冲突现场 → 一致性文明图谱拼合

不一致之雾逼你下注:五样东西,哪一样其实不需要数据库?逐个点击。
第一幕 · 自信→动摇

关系殿 · 表与代数

关系模型/关系代数 σ π ⋈ / 元组关系演算

推开殿门,迎面是一排排悬浮的表——行是元组,列是属性,表与表之间有看不见的连线。诺依曼老祖递给你三枚符印:σ、π、⋈。

诺依曼老祖 诺依曼老祖

「关系代数是过程性的——你要亲手排出运算顺序。σ选行、π选列、⋈连表。把'CS系学生选了哪些课'排出来。」

不一致之雾 不一致之雾

「写个 SELECT 不就完了?干嘛要排运算顺序——多此一举。」

关系代数运算台 · σ/π/⋈ 流水线

依次放置三种运算符 → 看流水线如何从两张表取出结果

第一幕 · 自信→动摇

SQL 炼炉 · 三咒与高阶

DDL/DML/DCL 三咒 + 查询分层展开 + 视图封装

关系殿深处是一座炼炉,三个炉口分别刻着 DDL、DML、DCL。墙上贴着九张咒文符纸——CREATE、SELECT、GRANT……散乱一片。

诺依曼老祖 诺依曼老祖

「SQL 是声明式的——你写'要什么',不写'怎么拿'。但这九张咒文分三类,投错炉口就炼废。投完再看一句 SELECT 怎么分层。」

SQL 炼炉 · 三咒分类 + 查询分层 + 视图封装

九张咒文投入正确炉口 → 查询分层展开 → 视图封装

第一幕 · 第一崩塌

设计阁 · 范式之缚

ER模型 / 函数依赖 / 1NF→2NF→3NF→BCNF / 更新异常

设计阁中央摆着一张大表——学号、姓名、课程、学分、院系、院系电话,全塞在一张表里。表身上布满裂纹,像随时会碎。诺依曼老祖皱眉。

诺依曼老祖 诺依曼老祖

「这张表违反了范式。点那三个按钮,看看会发生什么——插入、删除、修改,每个都会让数据自相矛盾。」

不一致之雾 不一致之雾

「一张表多省事,干嘛拆?来,我帮你改几笔——保证越改越乱。」

范式升降机推演器 · 异常复现 + ER建模 + 1NF→BCNF

触发三类更新异常 → ER建模拆表 → 范式滑块逐级愈合裂纹

反范式大表 · 异常复现沙盘

第二幕 · 深入

索引塔 · B+树与哈希

B+树建造 / 哈希分桶 / 查询形状匹配

索引塔是一座高塔,塔身是层层叠叠的节点。诺依曼老祖指着塔顶和塔基。

诺依曼老祖 诺依曼老祖

「B+树:内部节点只路由,数据全在叶子层,叶子用链表串起——范围查询友好。哈希:等值查询 O(1),但不支持范围。查询形状决定用哪个。」

索引塔 · B+树建造器 + 哈希分桶器 + 查询形状匹配器

插入键值建B+树 → 哈希分桶 → 匹配查询形状选索引

B+树建造器

哈希分桶器 · h(k)=k%4

查询形状匹配器 · 点格子判断索引适用性

第二幕 · 深入

执行计划镜 · 查询的秘密

执行计划并排 / 代价拆解 IO+CPU / 统计信息刷新 CBO

执行计划镜是一面巨大的镜子,同一句 SQL 在镜中映出三个不同的影子——顺序扫描、索引扫描、哈希连接,每个影子上都标着代价。

诺依曼老祖 诺依曼老祖

「优化器基于代价(CBO)选计划。代价 = IO + CPU。但代价靠统计信息估算——统计信息一陈旧,选错计划。」

不一致之雾 不一致之雾

「统计信息?那玩意儿反正会自动更新——不用管。」

执行计划镜 · 代价拆解 + 统计刷新

点三个计划看代价拆解 → ANALYZE 刷新统计 → 优化器重选

第二幕 · 深入

事务之环 · ACID 誓言

ACID 四环检验 / 隔离级别 / 并发异常矩阵

事务之环是四个悬浮的圆环——A、C、I、D——上面刻着誓言。诺依曼老祖让你依次触碰。

诺依曼老祖 诺依曼老祖

「A 靠 undo、C 靠约束、I 靠锁/MVCC、D 靠 redo。四承诺各有代价——没有一个免费的。测完再看并发双事务。」

不一致之雾 不一致之雾

「隔离级别?直接拉满 Serializable 不就完了——最安全嘛。」

事务之环 · ACID 四环检验 + 并发双事务沙盘

点 A/C/I/D 看检验 → 切换隔离级别看脏读/不可重复读/幻读

第二幕 · 第二崩塌

并发锁阵 · 2PL 与死锁

两阶段锁 2PL / 等待图画环 / 死锁处理三策略 / 事务之伤

锁阵是一片密密麻麻的锁具网格,两个事务 T1、T2 各持一盏灯。诺依曼老祖刚说完"2PL保证可串行化",T1 锁了 A,T2 锁了 B——然后它们互相对望,谁也不让谁。

诺依曼老祖 诺依曼老祖

「两阶段。先都加锁,再都放锁——2PL。但你看,T1 等 B,T2 等 A,等待图成环了。」

不一致之雾 不一致之雾

「死锁。你亲手造的。加锁即安全?呵——安全从来不是免费的。」

死锁等待图相图探索器 · 2PL + 画环 + 死锁处理

T1/T2 加锁 → 互相等待 → 等待图成环 → 选处理策略 → 事务之伤

2PL 加锁执行器

等待图画环器

第三幕 · 复苏

灾厄日志 · ARIES 复苏

WAL 原则 / Analysis / Redo / Undo / CLR / 事务之伤愈合

S7 留下的青色碎片还悬在半空——本命事务之伤未愈。灾厄日志殿里卷起一轴金色日志卷轴,上面刻满 LSN 序号。诺依曼老祖指着卷轴。

诺依曼老祖 诺依曼老祖

「WAL——先写日志,再改数据。日志在,就能重来。先组装 WAL 顺序,再走 ARIES 三阶段,把你的事务之伤补回来。」

不一致之雾 不一致之雾

「崩溃了重做 winner 不就行?干嘛要重复全部历史——多此一举。」

ARIES 三阶段公式组装器 · WAL + Analysis/Redo/Undo + CLR

组装 WAL 顺序 → Analysis 扫描 → Redo 重放全部历史 → Undo 倒序撤销写 CLR → 事务之伤愈合

WAL 原则组装 · 拖碎片到正确顺序

第1步
第2步
第3步
先写日志
日志落盘
改数据

日志卷轴扫描器

Analysis 分析

从检查点扫描日志,标记 winner/loser

Redo 重做

从最早脏页重放所有日志(重复历史)

Undo 撤销

对 loser 倒序撤销,每条写 CLR
第三幕 · 最高潮

Boss 战 · 不一致之雾

三问对决 · 雾账翻阅 · 排除法收网

日志殿灯火齐灭。灰雾从四面八方压过来,凝成一张巨大的、没有五官的脸——由无数行不一致的数据构成,同一个余额有三个不同的值。

不一致之雾 不一致之雾

「我是不一致之雾。你在每一处都欠了我的账——现在,一笔笔还。三问。答错一题,雾就深一分。第三问,用排除法——你走过的每一条死路,都会浮出来。」

渊账累计 0 笔 · 三问全对后清零

第三幕 · 收束

异界远眺 · NoSQL 与向量

NoSQL 对照 / LSM-tree / 列存对比 / 向量索引

雾散尽时数据筑基殿灯火重明。殿后推开一扇窗,窗外是另一片天地——NoSQL 的异界,规则全然不同。诺依曼老祖站在窗边。

诺依曼老祖 诺依曼老祖

「关系数据库不是唯一答案。NoSQL 舍关系完整性换伸缩,LSM-tree 舍读性能换写吞吐,列存舍行事务换分析 IO,向量索引舍精确换语义相似。每种存储都是一次权衡——和你刚走过的 ACID 权衡,本质一样。」

异界远眺 · NoSQL 对照 + LSM/列存/向量 + 知识图谱

对照4类NoSQL权衡 → LSM/列存/向量索引 → 点亮10块碎片 → 境界突破

LSM-tree · 写优化存储

列存对比 · 分析查询友好

向量索引 · 语义近邻搜索