PostgreSQL码农集散地

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 

AI 生成的内容请自行辨别正确性, 当然也多了些许踩坑的乐趣.