为什么手写一个数据库是技术分水岭

大多数后端工程师的瓶颈不在于会用 Redis 或 MySQL,而在于不理解数据是如何被持久化、并发控制以及如何保证一致性的。市面上讲数据库的课程,要么停留在 SQL 语法层面,要么只讲架构理论,缺乏从代码层面重构底层逻辑的实践环节。这门课填补的就是这个真空:它不教你怎么调优现成的数据库,而是教你从零搭建一个具备核心特性的数据库系统。对于想要突破“CRUD 工程师”标签、向底层基础设施领域转型的技术人员来说,这是一次极佳的系统级思维训练。

课程内容拆解与学习路径建议

课程的核心在于“手写”二字,意味着你需要亲自处理内存管理、日志恢复、锁机制等硬核问题。学习时,不要试图一次性吞下所有细节,建议按照以下逻辑推进:

首先,重点攻克**存储引擎层**。这是数据库的地基,理解数据页(Page)的结构、B+树索引的构建与维护,以及 WAL(预写式日志)的原理。这是后续所有高级特性的基础,如果这块没理清,后面的并发控制会非常吃力。

其次,深入**查询执行层**。关注 SQL 解析器如何工作,优化器如何选择执行计划,以及算子(Operator)是如何在内存中流式处理数据的。这一步能帮你理解为什么某些查询慢,以及数据库是如何避免全表扫描的。

最后,挑战**并发控制与事务管理**。这是最复杂的部分,涉及 MVCC(多版本并发控制)、锁粒度、隔离级别的实现。建议结合经典论文或源码(如 SQLite 或 MiniSQL)对照学习,理解学术界理论在实际工程中的取舍。

适合人群与资料使用指南

这门课适合有一定 Java 或 C++ 基础,且对操作系统、数据结构有较好理解的学员。如果你连链表、指针或 IO 模型都感到陌生,建议先补齐基础再入门。对于转行者或初级开发,这是一次高难度的跃迁;对于资深开发,这是重构知识体系的最佳时机。

资料包通常包含课件、核心代码片段以及参考实现。请务必以“主动编写”为主,资料仅作为脚手架。遇到报错时,不要直接复制答案,尝试通过打印内存状态、追踪日志来定位问题。只有当你的代码能正确处理崩溃恢复和并发冲突时,才算真正掌握了这门课的内容。学完后,你将具备独立分析数据库性能瓶颈、设计分布式存储方案的能力,这将是简历上极具分量的亮点。

课程目录

├── 1-课程介绍及学习指南/ │ └── [ 16M] 1-1 -1 课程导学 ├── 2-手写数据库系统的必要性,及系统的整体介绍/ │ ├── [ 19M] 2-1 为什么研究并实现一款数据库 │ ├── [5.2M] 2-2 我们希望设计一款怎样的数据库 │ ├── [9.1M] 2-3 如何快速实现原型,选择合适的语言 │ ├── [ 12M] 2-4 复杂项目的持续演进要点 │ └── [9.2M] 2-5 学习提前挖掘和识别可能的工程难点 ├── 3-研究优秀架构,教你如何进行复杂的软件设计/ │ ├── [ 28M] 3-1 手把手带你进行需求分析和架构设计 │ ├── [ 37M] 3-2 一起学习主流数据库架构,提升整体思维 │ ├── [7.9M] 3-3 深入了解数据库系统的各模块功能 │ ├── [ 13M] 3-4 如何设计好关键接口 │ ├── [ 38M] 3-5 代码实现:创建基本目录和模块 │ └── [ 21M] 3-6 代码实现:实现基本接口 ├── 4-学习SQL引擎,破解各种数据库优化的核心 │ ├── [ 41M] 4-1 深入学习SQL模块的原理 │ ├── [ 10M] 4-2 探索数据库SQL语句执行中的坑 │ ├── [ 16M] 4-3 了解编译原理,知道语句是如何变成执行计划的 │ ├── [ 42M] 4-4 代码实现:实现一个SQL语法解析器(一) │ ├── [ 40M] 4-5 代码实现:实现一个SQL语法解析器(二) │ ├── [ 46M] 4-6 代码实现:实现一个SQL语法解析器(三) │ ├── [ 21M] 4-7 代码实现:实现一个SQL语法解析器(四) │ ├── [ 52M] 4-8 代码实现:完善增删查改语句的逻辑(一) │ ├── [ 53M] 4-9 代码实现:完善增删查改语句的逻辑(二) │ ├── [ 16M] 4-

10 我们的产品应该支持哪些功能 │ ├── [ 19M] 4-

11 如何把语法树变成查询树 │ ├── [ 45M] 4-

12 代码实现:将AST转换为查询树(一) │ ├── [ 48M] 4-

13 代码实现:将AST转换为查询树(二) │ ├── [ 33M] 4-

14 代码实现:将AST转换为查询树(三) │ ├── [9.7M] 4-

15 学习问题发觉,识别现有工程的不足 │ ├── [ 28M] 4-

16 代价估计与计划选择 │ ├── [ 67M] 4-17 代码实现:回顾手动写语法解析的过程,并补齐树上的查询信息(一) │ ├── [ 51M] 4-18 代码实现:回顾手动写语法解析的过程,并补齐树上的查询信息(二) │ ├── [ 47M] 4-19 代码实现:回顾手动写语法解析的过程,并补齐树上的查询信息(三) │ ├── [3.8M] 4-

20 语法解析器还可以有哪些妙用? │ └── [7.6M] 4-

21 SQL层要点总结与后续演进分析 ├── 5-深入探索执行引擎,从根本上理解数据库是怎样跑起来的/ │ ├── [ 22M] 5-1 数据库是怎样跑起来的?核心算子解密 │ ├── [ 12M] 5-2 最直接的数据获取逻辑:扫描算子 │ ├── [ 15M] 5-3 为什么不一定要使用索引 │ ├── [ 59M] 5-4 代码实现:扫描算子的实现(一) │ ├── [ 49M] 5-5 代码实现:扫描算子的实现(二) │ ├── [ 47M] 5-6 代码实现:扫描算子的实现(三) │ ├── [ 48M] 5-7 代码实现:扫描算子的实现(四) │ ├── [ 72M] 5-8 代码实现:扫描算子的实现(五) │ ├── [ 10M] 5-9 代码实现:扫描算子的实现(练习题解答) │ ├── [9.3M] 5-

10 学习排序算子,破解语句执行慢的奥秘 │ ├── [ 29M] 5-

11 深度解密内排序、外排序的底层逻辑 │ ├── [ 49M] 5-

12 代码实现:实现排序算子(一) │ ├── [ 47M] 5-

13 代码实现:实现排序算子(二) │ ├── [ 47M] 5-

14 代码实现:实现排序算子(三) │ ├── [ 13M] 5-

15 为什么你的聚合过程这么慢?从聚合算子说起 │ ├── [ 60M] 5-

16 代码实现:聚合算子实现(一) │ ├── [ 49M] 5-

17 代码实现:聚合算子实现(二) │ ├── [ 54M] 5-

18 代码实现:聚合算子实现(三) │ ├── [ 70M] 5-

19 代码实现:聚合算子实现(四) │ ├── [ 34M] 5-

20 关系型数据库的重中之重:连接算子 │ ├── [8.7M] 5-

21 揭秘为什么有的公司严禁多表连接? │ ├── [ 45M] 5-

22 代码实现:连接算子实现(一) │ ├── [ 52M] 5-

23 代码实现:连接算子实现(二) │ ├── [ 66M] 5-

24 代码实现:连接算子实现(三) │ ├── [ 38M] 5-

25 代码实现:连接算子实现(四) │ ├── [8.5M] 5-

26 还有哪些算子十分重要? │ ├── [ 18M] 5-

27 为什么一个SQL语句可以产生很多执行计划? │ ├── [ 19M] 5-

28 如何选择一个较优的执行计划? │ ├── [ 67M] 5-

29 代码实现:对接计划选择和执行逻辑(一) │ ├── [ 53M] 5-

30 代码实现:对接计划选择和执行逻辑(二) │ ├── [ 58M] 5-

31 代码实现:对接计划选择和执行逻辑(三) │ ├── [ 67M] 5-

32 代码实现:对接计划选择和执行逻辑(四) │ └── [8.3M] 5-

33 执行层要点概览与演进分析 ├── 6-探秘存储引擎,观摩数据存储的精妙设计/ │ ├── 【更多it资源 www.】 │ ├── [ 11M] 6-1 探索存储层包含的子组件和原理 │ ├── [ 29M] 6-2 看看主流数据库是怎么实现存储引擎的 │ ├── [ 15M] 6-3 如果是内存数据库就会简单很多? │ ├── [ 57M] 6-4 代码实现:当作内存存储引擎来mock现有功能(一) │ ├── [ 69M] 6-5 代码实现:当作内存存储引擎来mock现有功能(二) │ ├── [ 63M] 6-6 代码实现:当作内存存储引擎来mock现有功能(三) │ ├── [ 47M] 6-7 代码实现:当作内存存储引擎来mock现有功能(四) │ ├── [ 28M] 6-8 如果放到磁盘上该怎么办? │ ├── [ 49M] 6-9 存储结构(页)设计与实现 │ ├── [ 35M] 6-

10 存储结构(页)设计与实现(一) │ ├── [ 37M] 6-

11 存储结构(页)设计与实现(二) │ ├── [ 37M] 6-

12 存储结构(页)设计与实现(三) │ ├── [ 29M] 6-

13 存储结构(页)设计与实现(四) │ ├── [ 51M] 6-

14 存储结构(页)设计与实现(五) │ ├── [ 62M] 6-

15 存储结构(页)设计与实现(六) │ ├── [ 20M] 6-

16 如何兼顾数据持久性和性能? │ ├── [ 14M] 6-

17 不同数据类型的存储方式是一样的吗? │ ├── [ 33M] 6-

18 非常重要的B+树算法 │ ├── [8.3M] 6-

19 为什么有的场景索引建得越多越不好? │ ├── [ 48M] 6-

20 代码实现:索引页的设计与实现(一) │ ├── [ 50M] 6-

21 代码实现:索引页的设计与实现(二) │ ├── [ 53M] 6-

22 代码实现:索引页的设计与实现(三) │ ├── [ 38M] 6-

23 代码实现:索引页的设计与实现(四) │ ├── [ 29M] 6-

24 代码实现:索引页的设计与实现(五) │ ├── [ 24M] 6-

25 代码实现:索引页的设计与实现(六) │ ├── [ 51M] 6-

26 代码实现:数据字典设计与实现(一) │ ├── [ 61M] 6-

27 代码实现:数据字典设计与实现(二) │ ├── [ 61M] 6-

28 代码实现:Buffer Pool设计与实现(一) │ ├── [ 58M] 6-

29 代码实现:Buffer Pool设计与实现(二) │ ├── [ 66M] 6-

30 代码实现:完善SQL层与存储层的联动(一) │ ├── [ 75M] 6-

31 代码实现:完善SQL层与存储层的联动(二) │ ├── [ 88M] 6-

32 代码实现:完善SQL层与存储层的联动(三) │ ├── [ 41M] 6-

33 代码实现:还有哪些DDL语句需要实现?(一) │ ├── [ 47M] 6-

34 代码实现:还有哪些DDL语句需要实现?(二) │ ├── [ 44M] 6-

35 代码实现:还有哪些DDL语句需要实现?(三) │ ├── [9.1M] 6-

36 数据库的参数管理还有这么多学问? │ ├── [ 55M] 6-37 代码实现:端到端完善执行功能,补充集成测试用例(一) │ ├── [ 59M] 6-38 代码实现:端到端完善执行功能,补充集成测试用例(二) │ ├── [ 66M] 6-39 代码实现:端到端完善执行功能,补充集成测试用例(三) │ ├── [ 77M] 6-40 代码实现:端到端完善执行功能,补充集成测试用例(四) │ ├── [ 71M] 6-41 代码实现:端到端完善执行功能,补充集成测试用例(五) │ └── [9.4M] 6-

42 存储层要点概览与演进分析 ├── 7-学习事务管理器原理,探秘数据库左右企业命脉的原因/ │ ├── [ 12M] 7-1 什么是事务的定义?为什么要支持事务? │ ├── [4.8M] 7-2 我们此时的数据库支持哪些事务特征? │ ├── [ 29M] 7-3 重要且经久不衰的ARIES算法 │ ├── [ 28M] 7-4 数据能够持久存储的关键:WAL设计与实现 │ ├── [ 29M] 7-5 事务回滚机制就像windows操作系统的回收站 │ ├── [ 16M] 7-6 代码实现:WAL过程实现(一) │ ├── [ 38M] 7-7 代码实现:WAL过程实现(二) │ ├── [ 49M] 7-8 代码实现:WAL过程实现(三) │ ├── [ 42M] 7-9 代码实现:WAL过程实现(四) │ ├── [ 40M] 7-

10 代码实现:WAL过程实现(五) │ ├── [ 52M] 7-

11 代码实现:WAL过程实现(六) │ ├── [ 56M] 7-

12 代码实现:WAL过程实现(七) │ ├── [ 27M] 7-

13 代码实现:WAL过程实现(八) │ ├── [100M] 7-

14 代码实现:WAL过程实现(九) │ ├── [ 61M] 7-

15 代码实现:WAL过程实现(十) │ ├── [ 69M] 7-

16 代码实现:WAL过程实现(十一) │ ├── [5.9M] 7-

17 完善一个单session数据库还需要做哪些工作 │ ├── [ 21M] 7-

18 怎么做好事务的隔离呢? │ ├── [ 17M] 7-

19 深度探索事务隔离机制 │ ├── [ 16M] 7-

20 代码实现:尝试用代码描述事务隔离 (一) │ ├── [ 54M] 7-

21 代码实现:尝试用代码描述事务隔离 (二) │ ├── [ 52M] 7-

22 代码实现:尝试用代码描述事务隔离(三) │ └── [3.6M] 7-

23 事务管理器要点概览与演进分析 ├── 8-见微知著,从数据库的网络层学习高吞吐的奥秘/ │ ├── @更多it资源 www. │ ├── [ 17M] 8-1 如何实现一个CS架构的数据库? │ ├── [7.9M] 8-2 假如让SQLite支持网络访问,应该怎么做设计? │ ├── [10.0M] 8-3 数据库的网络层实现还有很多工程技巧? │ ├── [ 31M] 8-4 代码实现:wire-protocol实现 (一) │ ├── [ 73M] 8-5 代码实现:wire-protocol实现 (二) │ ├── [ 50M] 8-6 代码实现:wire-protocol实现 (三) │ ├── [ 59M] 8-7 代码实现:wire-protocol实现 (四) │ ├── [ 37M] 8-8 代码实现:wire-protocol实现(五) │ ├── [8.0M] 8-9 代码实现:wire-protocol实现 (六) │ ├── [ 33M] 8-

10 一个端到端测试网络访问的逻辑(一) │ ├── [ 41M] 8-

11 一个端到端测试网络访问的逻辑(二) │ ├── [ 78M] 8-

12 一个端到端测试网络访问的逻辑(三) │ ├── [ 42M] 8-

13 探索实现一个benchmark │ └── [2.2M] 8-

14 网络层实现要点回顾 ├── 9-由内到外,探索数据库周边技术/ │ ├── [8.6M] 9-1 思考:我们的产品原型与主流关系数据库还有多大差距? │ ├── [6.7M] 9-2 通过对比主流数据库,发现易用性的奥秘 │ ├── [7.4M] 9-3 学习让数据库跑得更快的黑科技 │ ├── [ 43M] 9-4 探索instrument的奥秘 │ ├── [ 19M] 9-5 实现ACL形式的权限验证逻辑 │ ├── [4.9M] 9-6 探讨不同数据模型的演进方向 │ └── [1.8M] 9-7 本章总结与挖坑 ├── 10-活学活用,高频面试题归纳与思考/ │ ├── [ 25M] 10-1 数据库实现中涉及到哪些算法和数据结构? │ ├── [8.5M] 10-2 为什么数据库要有Buffer层,不可以用操作系统的Cache吗? │ ├── [ 16M] 10-3 对于整个系统,是否索引越多越好?为什么? │ ├── [ 16M] 10-4 都有哪些子句可能会用到索引?说说你索引配置的思路? │ └── [7.4M] 10-5 课程作业 ├── 11-课程总结/ │ └── [ 11M] 11-1 课程总结