DBA转型干内核开发行不行?
专为DBA设计数据库内核开发学习指南
转型成功的有吗?有,而且不乏大家熟悉的大神们!有了AI的加持,转型将更加丝滑。DBA的优势那可就多了,比如对数据库体系的理解,对业务的理解,能跟开发好得穿一条裤子一样的只有DBA,可不像产品经理是开发的大冤家。最重要的是DBA多酒量好,写出来的代码bug可以自带酱香。
一起来写酱香味的bug,别整天删库跑路了。
课程目标:
理解数据库内核的核心概念和架构。 掌握PostgreSQL内核的关键模块和代码结构。 学习数据库存储引擎、索引、查询优化、事务并发控制、日志恢复等核心技术的实现原理。 具备开发和扩展数据库内核的能力,能够进行性能调优和故障排除。 了解不同数据库产品的设计理念和实现方式,进行对比学习。
课程结构:
本课程分为六个主要章节,每个章节包含理论讲解、PostgreSQL代码分析、基础实验和厂商扩展实验。
预备知识:通用工具介绍
GDB (GNU Debugger) 使用GDB调试简单的C程序。 使用GDB连接到PostgreSQL进程进行调试。 设置断点,查看变量,分析程序执行流程。 理论:GDB的基本概念、调试流程、常用命令(断点、单步执行、查看变量、堆栈跟踪)。 实践: Valgrind 使用Valgrind Memcheck检测C程序的内存泄漏。 使用Valgrind Cachegrind进行性能分析。 分析PostgreSQL程序的内存使用情况和性能瓶颈。 理论:Valgrind的基本概念、内存泄漏检测、性能分析。 实践:
第一章:存储引擎与数据组织
1.1 行存储与页面结构 (MySQL) 分析InnoDB的COMPACT行格式。 (SQLite) 分析SQLite的页面结构和B-Tree实现。 (DuckDB) 分析DuckDB的行存储格式和向量化执行的页面布局。 使用 pageinspect扩展查看PG数据页二进制结构。编写C函数修改 pd_lsn模拟页面损坏并触发恢复。GDB: 使用GDB调试C函数,观察变量变化,验证修改是否正确。 Valgrind: 使用Valgrind Memcheck检查C函数是否存在内存泄漏。 理论:Heap Tuple结构、PageHeader字段解析、页面组织方式(链表、B-Tree等) PG代码分析: src/include/storage/bufpage.h中Page布局、src/backend/storage/page/目录下的相关代码基础实验: 厂商扩展实验: 1.2 堆表 (Oracle) 分析Oracle的堆表组织方式和数据管理。 (PolarDB) 分析PolarDB的堆表优化技术。 实现一个简单的堆表存储引擎,支持基本的CRUD操作。 分析PG堆表的vacuum机制。 GDB: 使用GDB调试堆表引擎,观察数据插入、更新、删除过程。 Valgrind: 使用Valgrind Memcheck检查堆表引擎是否存在内存泄漏。 GDB: 使用GDB跟踪vacuum过程,观察页面回收和索引更新。 理论:堆表的组织方式、数据插入、更新、删除操作的实现。 PG代码分析: src/backend/access/heap/目录下的相关代码。基础实验: 厂商扩展实验: 1.3 索引组织表 (Oracle) 分析Oracle的索引组织表(IOT)的实现。 (MySQL) 分析InnoDB的聚簇索引的实现。 基于PG的B-Tree索引,实现一个简单的索引组织表。 GDB: 使用GDB调试索引组织表,观察索引和数据的同步过程。 Valgrind: 使用Valgrind Memcheck检查索引组织表是否存在内存泄漏。 理论:索引组织表的概念、优点和缺点、数据组织方式。 PG代码分析:PostgreSQL本身没有直接的索引组织表,可以分析MySQL InnoDB的聚簇索引表的实现。 基础实验: 厂商扩展实验: 1.4 列存表 (ClickHouse) 分析ClickHouse的列存实现和压缩算法。 (DuckDB) 分析DuckDB的列存实现和向量化执行。 使用 cstore_fdw插件,创建一个列存表,并进行查询。分析列存表的压缩算法。 Valgrind: 使用Valgrind Cachegrind分析列存表的查询性能。 理论:列存表的概念、优点和缺点、数据组织方式、压缩技术。 PG代码分析:了解PG的列存插件(如 cstore_fdw)。基础实验: 厂商扩展实验: 1.5 LSM-Tree (LevelDB/RocksDB) 分析LevelDB/RocksDB的LSM-Tree实现。 (ClickHouse) ClickHouse MergeTree引擎的类似LSM-Tree的实现。 设计一个简单的LSM-Tree存储引擎。 分析LSM-Tree的Compaction过程。 GDB: 使用GDB调试LSM-Tree引擎,观察数据写入和Compaction过程。 Valgrind: 使用Valgrind Memcheck检查LSM-Tree引擎是否存在内存泄漏。 理论:LSM-Tree的概念、优点和缺点、数据组织方式、Compaction过程。 PG代码分析:PostgreSQL本身没有LSM-Tree,可以讨论如何基于插件实现。 基础实验: 厂商扩展实验: 1.6 行列混合存储 (ZedStore) (Greenplum) 分析 Greenplum 的行列混合存储实现。 (ClickHouse) 分析 ClickHouse 的列式存储实现。 ZedStore 架构分析: 了解 ZedStore 的整体架构,包括存储层、索引层、查询层等。 数据组织方式: 分析 ZedStore 如何将数据组织成行和列的混合形式。 代码阅读: 阅读 ZedStore 的关键代码,例如数据写入、读取、索引构建等。 实验: 编译和安装 ZedStore: 将 ZedStore 集成到 PostgreSQL 中。 创建和查询 ZedStore 表: 创建一个 ZedStore 表,并进行查询操作。 性能分析: 使用 Valgrind Cachegrind 分析 ZedStore 的查询性能。 代码修改: 修改 ZedStore 的代码,例如添加新的数据类型、优化查询性能等。 GDB: 使用 GDB 调试 ZedStore 代码,观察数据写入和读取过程。 Valgrind: 使用 Valgrind Memcheck 检查 ZedStore 代码是否存在内存泄漏。 理论:行列混合存储的概念、优点和缺点、数据组织方式。 PG代码分析:了解PG中如何通过分区表和不同的存储引擎实现行列混合存储。 ZedStore 代码阅读与实现: 厂商扩展实验: 1.7 内存列存表 (MemSQL) 分析MemSQL的内存列存实现。 (DuckDB) 分析DuckDB的内存列存实现和向量化执行。 使用PG的 in-memory表和cstore_fdw插件,创建一个内存列存表,并进行查询。Valgrind: 使用Valgrind Cachegrind分析内存列存表的查询性能。 理论:内存列存表的概念、优点和缺点、数据组织方式、适用场景。 PG代码分析:了解PG中如何使用 in-memory表和列存插件实现内存列存表。基础实验: 厂商扩展实验:
第二章:索引实现与优化
2.1 B-Tree (MySQL) 分析InnoDB的B+Tree索引实现。 (Oracle) 分析Oracle的B-Tree索引实现。 实现一个简单的B-Tree索引。 分析PG B-Tree索引的页面分裂和合并过程。 GDB: 使用GDB调试B-Tree索引,观察插入、删除、查找过程。 Valgrind: 使用Valgrind Memcheck检查B-Tree索引是否存在内存泄漏。 GDB: 使用GDB跟踪页面分裂和合并过程,观察页面结构变化。 理论:B-Tree的结构、插入、删除、查找操作、优化策略。 PG代码分析: src/backend/access/nbtree/目录下的相关代码。基础实验: 厂商扩展实验: 2.2 Hash (MySQL) 分析MySQL的Hash索引实现。 实现一个简单的Hash索引。 分析PG Hash索引的冲突解决策略。 GDB: 使用GDB调试Hash索引,观察冲突解决过程。 Valgrind: 使用Valgrind Memcheck检查Hash索引是否存在内存泄漏。 理论:Hash索引的结构、冲突解决策略、适用场景。 PG代码分析: src/backend/access/hash/目录下的相关代码。基础实验: 厂商扩展实验: 2.3 GIN 使用GIN索引加速文本搜索。 分析GIN索引的更新过程。 Valgrind: 使用Valgrind Cachegrind分析GIN索引的查询性能。 GDB: 使用GDB跟踪GIN索引的更新过程,观察索引结构变化。 理论:GIN索引的结构、倒排索引、适用场景。 PG代码分析: src/backend/access/gin/目录下的相关代码。基础实验: 2.4 GiST 使用GiST索引加速空间数据搜索。 分析GiST索引的插入和查询过程。 Valgrind: 使用Valgrind Cachegrind分析GiST索引的查询性能。 GDB: 使用GDB跟踪GiST索引的插入和查询过程,观察索引结构变化。 理论:GiST索引的结构、可扩展性、适用场景。 PG代码分析: src/backend/access/gist/目录下的相关代码。基础实验: 2.5 SP-GiST 使用SP-GiST索引加速空间数据搜索。 分析SP-GiST索引的平衡策略。 Valgrind: 使用Valgrind Cachegrind分析SP-GiST索引的查询性能。 GDB: 使用GDB跟踪SP-GiST索引的平衡过程,观察索引结构变化。 理论:SP-GiST索引的结构、空间数据索引、适用场景。 PG代码分析: src/backend/access/spgist/目录下的相关代码。基础实验: 2.6 BRIN 使用BRIN索引加速时序数据搜索。 分析BRIN索引的存储空间占用。 Valgrind: 使用Valgrind Cachegrind分析BRIN索引的查询性能。 理论:BRIN索引的结构、块范围索引、适用场景。 PG代码分析: src/backend/access/brin/目录下的相关代码。基础实验: 2.7 Bloom (ClickHouse) 分析ClickHouse的Bloom Filter索引实现。 使用Bloom Filter加速查询。 分析Bloom Filter的误判率。 Valgrind: 使用Valgrind Cachegrind分析Bloom Filter的查询性能。 理论:Bloom Filter的结构、概率型数据结构、适用场景。 PG代码分析:了解PG中如何使用Bloom Filter进行查询优化。 基础实验: 厂商扩展实验: 2.8 HNSW 使用HNSW索引加速向量相似度搜索。 分析HNSW索引的构建过程。 Valgrind: 使用Valgrind Cachegrind分析HNSW索引的查询性能。 理论:HNSW图索引的结构、近似最近邻搜索、适用场景。 PG代码分析:了解PG中如何使用HNSW索引进行向量相似度搜索(通过插件)。 基础实验: 2.9 IVFFlat (milvus) 分析milvus 向量索引实现。 使用IVFFlat索引加速向量相似度搜索。 分析IVFFlat索引的量化过程。 Valgrind: 使用Valgrind Cachegrind分析IVFFlat索引的查询性能。 理论:IVFFlat索引的结构、向量量化、近似最近邻搜索、适用场景。 PG代码分析:了解PG中如何使用IVFFlat索引进行向量相似度搜索(通过插件)。 基础实验: 厂商扩展实验:
第三章:查询解析与优化及执行
3.1 解析 使用 pg_parse扩展查看SQL语句的语法树。修改SQL语法分析器,添加自定义SQL语法。 GDB: 使用GDB调试SQL解析器,观察语法树的生成过程。 理论:SQL语法分析、词法分析、语法树生成。 PG代码分析: src/backend/parser/目录下的相关代码。基础实验: 3.2 规则重写 编写自定义查询重写规则。 分析PG的视图展开过程。 GDB: 使用GDB调试查询重写器,观察规则的应用过程。 理论:查询重写规则、视图展开、子查询优化。 PG代码分析: src/backend/optimizer/rewriter/目录下的相关代码。基础实验: 3.3 优化 使用 EXPLAIN命令分析查询执行计划。修改查询优化器的代价模型。 Valgrind: 使用Valgrind Cachegrind分析不同执行计划的性能。 理论:查询优化器、代价模型、执行计划生成。 PG代码分析: src/backend/optimizer/path/和src/backend/optimizer/plan/目录下的相关代码。基础实验: 3.4 执行 编写自定义查询执行算子。 分析PG的查询执行过程。 GDB: 使用GDB调试查询执行算子,观察数据流的传递过程。 Valgrind: 使用Valgrind Memcheck检查查询执行算子是否存在内存泄漏。 理论:查询执行器、算子实现、数据流模型。 PG代码分析: src/backend/executor/目录下的相关代码。基础实验: 3.5 火山引擎 实现一个简单的火山引擎。 分析PG的火山引擎执行过程。 GDB: 使用GDB调试火山引擎,观察迭代器模式的实现。 Valgrind: 使用Valgrind Cachegrind分析火山引擎的性能。 理论:火山模型、迭代器模式、数据流处理。 PG代码分析:PG的查询执行器基于火山模型。 基础实验: 3.6 向量化引擎 (ClickHouse) 分析ClickHouse的向量化执行引擎。 (DuckDB) 分析DuckDB的向量化执行引擎。 使用向量化执行加速查询。 分析向量化执行的性能提升。 Valgrind: 使用Valgrind Cachegrind分析向量化执行的性能提升。 理论:向量化执行、SIMD指令、数据并行处理。 PG代码分析:了解PG中如何使用向量化执行(通过插件)。 基础实验: 厂商扩展实验:
第四章:事务与并发控制
4.1 事务ACID属性 模拟事务执行过程,验证ACID属性。 GDB: 使用GDB调试事务执行过程,观察事务状态变化。 理论:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)的定义和实现机制。 PG代码分析: src/backend/access/transam/目录下的相关代码。基础实验: 4.2 并发控制协议 实现一个简单的锁管理器。 分析PG的锁机制和死锁检测。 GDB: 使用GDB调试锁管理器,观察锁的获取和释放过程。 Valgrind: 使用Valgrind Memcheck检查锁管理器是否存在内存泄漏。 理论:锁机制、两阶段锁协议(2PL)、时间戳排序(Timestamp Ordering)、乐观并发控制(OCC)。 PG代码分析: src/backend/storage/lmgr/目录下的相关代码。基础实验: 4.3 隔离级别 在不同隔离级别下执行并发事务,观察结果。 分析PG的隔离级别实现。 GDB: 使用GDB调试并发事务,观察不同隔离级别下的数据可见性。 理论:读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)、串行化(Serializable)的定义和实现。 PG代码分析: src/backend/access/transam/目录下的相关代码。基础实验: 4.4 多版本并发控制(MVCC) (MySQL) 分析InnoDB的MVCC实现。 (Oracle) 分析Oracle的MVCC实现。 分析PG的MVCC实现。 模拟MVCC的快照隔离过程。 GDB: 使用GDB调试MVCC,观察版本链的生成和维护过程。 理论:MVCC的原理、快照隔离、版本链。 PG代码分析: src/backend/access/heap/目录下的相关代码。基础实验: 厂商扩展实验: 4.5 死锁检测与避免 模拟死锁场景,观察PG的死锁检测。 实现一个简单的死锁检测算法。 GDB: 使用GDB调试死锁检测器,观察死锁的检测过程。 理论:死锁的产生条件、死锁检测算法、死锁避免策略。 PG代码分析: src/backend/storage/lmgr/目录下的相关代码。基础实验:
第五章:日志与恢复机制
5.1 WAL(Write-Ahead Logging) 分析PG的WAL日志格式。 模拟WAL的写入过程。 GDB: 使用GDB调试WAL写入过程,观察日志记录的生成。 理论:WAL的原理、日志记录格式、检查点机制。 PG代码分析: src/backend/access/transam/和src/backend/wal/目录下的相关代码。基础实验: 5.2 检查点(Checkpoint) 分析PG的检查点过程。 模拟检查点的写入过程。 GDB: 使用GDB调试检查点过程,观察脏页的写入过程。 理论:检查点的作用、检查点过程、检查点优化。 PG代码分析: src/backend/wal/目录下的相关代码。基础实验: 5.3 崩溃恢复(Crash Recovery) 模拟数据库崩溃,观察PG的恢复过程。 分析PG的崩溃恢复日志。 GDB: 使用GDB调试崩溃恢复过程,观察日志回放过程。 理论:崩溃恢复的原理、日志回放、未完成事务的处理。 PG代码分析: src/backend/access/transam/和src/backend/wal/目录下的相关代码。基础实验: 5.4 PITR(Point-in-Time Recovery) 使用PG的PITR功能进行数据恢复。 分析PITR的恢复过程。 理论:PITR的原理、基于WAL的恢复、备份与恢复策略。 PG代码分析:了解PG的PITR实现。 基础实验: 5.5 逻辑复制(Logical Replication) 配置PG的逻辑复制。 分析逻辑复制的数据同步过程。 理论:逻辑复制的原理、基于逻辑解码的复制、数据同步。 PG代码分析: src/backend/replication/目录下的相关代码。基础实验:
第六章:高级特性扩展
6.1 自定义类型 创建一个自定义类型,并定义相关的操作符。 使用自定义类型进行数据存储和查询。 GDB: 使用GDB调试自定义类型,观察操作符的调用过程。 理论:自定义类型的定义、操作符重载、类型转换。 PG代码分析: src/backend/catalog/目录下的相关代码。基础实验: 6.2 CustomScan接口 实现一个自定义扫描算子,并集成到PG的查询执行器中。 使用CustomScan接口加速查询。 GDB: 使用GDB调试CustomScan算子,观察数据扫描过程。 Valgrind: 使用Valgrind Cachegrind分析CustomScan算子的性能。 理论:CustomScan接口的作用、自定义扫描算子的实现。 PG代码分析: src/include/nodes/extensible.h和src/backend/optimizer/path/目录下的相关代码。基础实验: 6.3 Index Access Method接口 实现一个自定义索引,并集成到PG的索引管理器中。 使用Index Access Method接口加速查询。 GDB: 使用GDB调试自定义索引,观察索引的构建和查询过程。 Valgrind: 使用Valgrind Memcheck检查自定义索引是否存在内存泄漏。 理论:Index Access Method接口的作用、自定义索引的实现。 PG代码分析: src/include/access/amapi.h和src/backend/access/目录下的相关代码。基础实验: 6.4 Table Access Method接口 实现一个自定义存储引擎,并集成到PG的存储管理器中。 使用Table Access Method接口实现自定义存储。 GDB: 使用GDB调试自定义存储引擎,观察数据的存储和读取过程。 Valgrind: 使用Valgrind Memcheck检查自定义存储引擎是否存在内存泄漏。 理论:Table Access Method接口的作用、自定义存储引擎的实现。 PG代码分析: src/include/access/tableam.h和src/backend/access/目录下的相关代码。基础实验: 6.5 Foreign Data Wrapper接口 使用Foreign Data Wrapper接口访问外部数据源(如MySQL、CSV文件)。 分析Foreign Data Wrapper接口的数据传输过程。 GDB: 使用GDB调试Foreign Data Wrapper,观察数据传输过程。 理论:Foreign Data Wrapper接口的作用、访问外部数据源。 PG代码分析: src/include/foreign/fdwapi.h和src/backend/foreign/目录下的相关代码。基础实验: 6.6 SQL语法扩展 添加自定义SQL命令,并集成到PG的SQL解析器中。 使用自定义SQL命令进行数据操作。 GDB: 使用GDB调试SQL解析器,观察自定义SQL命令的解析过程。 理论:SQL语法扩展的原理、自定义SQL命令的实现。 PG代码分析: src/backend/parser/目录下的相关代码。基础实验: 6.7 插件的开发和发布 开发一个简单的PG插件,并发布到PG的扩展库中。 分析PG插件的加载和卸载过程。 理论:PG插件的开发流程、插件的编译和安装、插件的发布。 PG代码分析:了解PG插件的开发规范。 基础实验:
备注:
本课程大纲可以根据实际情况进行调整。 每个章节的厂商扩展实验可以根据邀请到的专家进行调整。 鼓励学生积极参与讨论和提问。
以上内容基于DeepSeek-R1和Gemini 2.0 Flash生成, 轻微人工调整, 感谢 杭州深度求索人工智能基础技术研究有限公司 及 google