1. 从会用数据库到研究内核这门大作业到底在逼你做什么如果你正在电子科技大学修数据库相关的课程大概率会遇到这门《PostgreSQL数据库内核技术研究实践》大作业。说句实在话很多同学第一次看到这个题目时的反应是我平时MySQL用得挺溜增删改查、建索引、写存储过程都熟怎么突然就要我去碰内核了这个心态我太理解了。因为会用数据库和研究数据库内核之间隔着的不是一点点代码量而是完全不同的思维层次。用数据库时你面对的是SQL语句和结果集一切就像黑盒——你告诉它帮我查出最近30天订单金额大于5000的用户它啪一下给你结果你根本不需要知道它背后是怎么扫描、怎么排序、怎么利用索引的。但内核研究不一样。它逼着你把黑盒打开看清楚里头的齿轮怎么咬合、润滑剂往哪儿流、哪个零件在什么条件下会过热。这就像开车和修发动机的区别前者只要会踩油门打方向盘后者得懂曲轴、活塞、气门正时那一整套机械原理。据我了解这门大作业在成电的开设背景是国内高校数据库教学从应用型往系统型转型的一个典型代表。过去教SQL、教调优学生毕业后到企业里写写业务代码还行但一遇到数据库性能瓶颈、内核级Bug就抓瞎。而像PostgreSQL这种开源关系型数据库代码结构清晰、社区活跃、文档完善正好是教学研究的最佳载体。PG的源码量虽然不小大概一百多万行C代码但核心架构非常优雅分层清晰比研究MySQL那盘根错节的代码要友好得多。所以这门大作业的真实目的不是什么为难你而是想让你通过动手实践真正建立起对数据库底层运行机制的理解。你不需要成为一个内核开发专家——那是十几年资历的工程师干的事——但你需要在课程结束时能回答清楚下面这组问题PostgreSQL收到一条SQL语句后从网络协议解析到返回结果中间经历了哪几个核心阶段表数据在磁盘上到底是怎么存的一个查询为什么有时候走索引有时候不走事务的原子性和隔离性是靠什么机制实现的为什么崩溃后数据库还能恢复如果让你给PG加一个新功能比如一个新的索引类型或者一个新的执行算子你要动哪些文件、改哪些接口这些问题考试背答案没用必须自己把代码读进去、把调试器跑起来、把断点打对位置才能真明白。这篇文章里我会按从零开始构建PostgreSQL调试环境 → 理解核心模块代码结构 → 选定一个研究点深入分析 → 完成实验报告和代码实验这条完整链路把我自己和身边同学在做类似项目时的经验、踩过的坑、值得借鉴的方法全部摊开讲。如果你是第一次接触数据库内核这篇文章可以当你的操作地图如果你已经有一定基础但卡在某个环节后面几节的排查思路也能给你一些启发。2. 版本选择和源码编译第一关就卡住大半人的地方先聊一个最常见的迷惑点PostgreSQL到底该下载哪个版本很多同学一上来就搜postgresql下载哪个版本然后装了个最新版比如17或者18的开发版结果编译完发现和课程资料对不上文档里写的函数找不到调试符号也怪怪的。这个坑我见过太多次了。2.1 学习内核研究首选的版本如果你是为了研究内核、读源码、做实验我强烈建议选PostgreSQL 14或者15这样的成熟稳定版本而不是追最新。原因很简单社区文档和源码解读资料最丰富。网上能搜到的内核分析文章、课程讲义、源码阅读笔记大部分基于12到15这个区间。你用15能找到大量对照资料如果用17、18很多结构变了遇到问题连参考都难找。核心架构足够完整。PostgreSQL的三大核心子系统——进程模型Postmaster Backend、存储管理Buffer Manager Storage Manager、事务与WALWrite-Ahead Logging——在14/15版本中形态非常经典非常适合教学拆解。更新的版本虽然加了增量备份、逻辑复制增强这些功能但那些都是增量改进不是架构性变化。编译要求友好。老版本对新版GCC、CMake的兼容性问题更少。新版本有时候会遇到奇怪的编译错误排查起来纯属浪费时间。建议直接去PostgreSQL官方源码仓库拉取对应分支git clone --branch REL_15_STABLE https://github.com/postgres/postgres.git注意用REL_15_STABLE而不是master。稳定分支上代码经过充分测试而且分支tag对应官方正式版本不会出现昨天还能编过今天就不行的尴尬事。2.2 Ubuntu上从源码编译的完整过程这一步是很多人的拦路虎所以我把完整过程写清楚。操作系统建议Ubuntu 22.04 LTS这也是目前很多学校实验室的标准环境。先装依赖sudo apt update sudo apt install -y build-essential bison flex libreadline-dev zlib1g-dev这几样缺一不可build-essential提供GCC和makebison和flex是用来生成SQL语法解析器的PG的语法分析器就是靠这两个工具从.y和.l文件生成的libreadline-dev是psql命令行交互必需的zlib1g-dev是压缩数据页用的。然后进入源码目录配置编译选项cd postgres ./configure --prefix/home/yourname/pg15 --enable-debug --enable-cassert这里有两个参数我要特别强调——--enable-debug是在编译时加入-g调试符号没有这个参数你后面用GDB调试时看到的只是函数名里面的变量值、行号全都没有等于白瞎。--enable-cassert会开启一系列运行时断言检查。它能帮你快速发现内存越界、状态异常这类内核Bug代价是性能下降一些。做研究绝对值得开。然后编译和安装make -j$(nproc) # 多核并行编译快很多 make install第一次编译大概要五到十分钟取决于机器配置。如果你看到All of PostgreSQL successfully made. Ready to install.就说明成功了。2.3 常见编译错误与排查思路编译踩坑太常见了这里列几个我见过的高频问题和对应的解决办法问题一flex或bison版本不对报错通常长这样scan.l: unknown error: ... required flex version ...PG对flex和bison的版本有最低要求但版本太新有时也会出问题比如某些版本的flex生成的代码和GCC不兼容。解决办法装稳定版bash sudo apt install -y flex bison如果还是报版本问题就检查一下是不是PATH里有别的旧版本工具干扰。 **问题二readline相关的链接错误** 报错里会出现cannot find -lreadline或者找不到readline.h。一般就是缺了开发头文件 bash sudo apt install -y libreadline-dev问题三内存不够导致编译过程被杀掉如果你用了-j$(nproc)而机器只有4G内存并行编译十几个文件时可能被Linux OOM Killer干掉。这时候老老实实少开几个并行任务make -j2问题四configure的时候找不到libzsudo apt install -y zlib1g-dev还有一个特别容易忽略的细节源码目录路径中不能有中文和空格。有些同学把代码放在课程作业这种目录下面GNU make有的版本会抽风。统一用英文路径别给自己找麻烦。编译安装完用/home/yourname/pg15/bin/postgres --version验证一下能输出版本号就说明这一关过了。3. 初始化集群与调试环境配置读内核代码的第一步是抓住一个活的内核编译只是第一步。更关键的是把PostgreSQL跑起来并且配置好调试工具这样你才能在代码层面看到它到底在干什么。3.1 初始化数据目录和启动实例PostgreSQL和其他数据库不太一样它需要你先初始化一个数据目录data directory里面存放所有配置文件、数据库模板、WAL日志等。执行mkdir -p ~/pgdata /home/yourname/pg15/bin/initdb -D ~/pgdata -U postgres --encodingUTF8 --localeC这里解释一下参数含义-U postgres设置数据库超级用户的名称。--encodingUTF8默认字符集做中文数据处理时用UTF8最省事。--localeC设置C locale。这里有个大坑——如果你的系统locale是中文的initdb的时候不指定locale可能会出现排序行为异常后面编译运行其他程序也可能受影响。然后启动服务/home/yourname/pg15/bin/pg_ctl -D ~/pgdata -l ~/pgdata/logfile start再用psql连进去试试/home/yourname/pg15/bin/psql -h localhost -U postgres -d postgres看到postgres#提示符就说明服务正常。3.2 让GDB能够定位到内核源码环境搭建最核心的部分来了——怎么让GDB调试一个正在运行的PostgreSQL后端进程。首先要明确一个概念PostgreSQL是多进程架构不是多线程架构。你启动服务后会有一个主进程postmaster在监听端口每当有新的客户端连接进来它就fork()一个子进程postgres后端进程来处理这个连接上的所有查询。研究查询执行、事务处理这些逻辑盯的就是这个后端进程。两种调试方式方式一提前启动一个backends用gdb attach上去先找一个会话连上数据库让这个会话保持空闲。找到它的进程IDps -ef | grep postgres你会看到类似这样的输出postgres 12345 1 0 10:30 ? 00:00:00 /home/yourname/pg15/bin/postgres -D /home/yourname/pg15/data postgres 12346 12345 0 10:30 ? 00:00:00 postgres: checkpointer postgres 12347 12345 0 10:30 ? 00:00:00 postgres: background writer postgres 12348 12345 0 10:30 ? 00:00:00 postgres: walwriter postgres 12349 12345 0 10:30 ? 00:00:00 postgres: autovacuum launcher postgres 12350 12345 0 10:30 ? 00:00:00 postgres: logical replication launcher postgres 12351 12345 0 10:35 ? 00:00:00 postgres: postgres postgres [local] idle最后一行的[local] idle就是那个保持连接的客户端会话。记住它的PID这里是12351然后用root或者同权限用户执行sudo gdb -p 12351进入GDB后加载符号(gdb) file /home/yourname/pg15/bin/postgres (gdb) continue好了现在GDB已经attach上去了。你在psql里随便执行一条SQL比如SELECT * FROM pg_class LIMIT 1;GDB就会在命中断点的地方停下来现在还没断点所以不会停但你可以随时CtrlC中断它输入bt查看堆栈。方式二直接用gdb启动postmaster先把服务停掉/home/yourname/pg15/bin/pg_ctl -D ~/pgdata stop然后gdb --args /home/yourname/pg15/bin/postgres -D ~/pgdata这种方式的好处是能调试启动阶段和postmaster自身的逻辑坏处是所有客户端连接都在一起被fork出来的进程不受GDB控制调试起来反而乱。核心里的大多数功能在后端进程所以方式一更好用。提示用set follow-fork-mode child这个GDB命令可以让GDB在postmaster fork之后自动跟随子进程。调试连接建立过程时这招很管用。3.3 那些方便到哭的调试技巧调试PostgreSQL内核有几个技巧我必须写出来按重要程度排技巧一用GDB的break命令配合符号断点这是最基本也最常用的。比如我想在查询执行的主入口exec_simple_query处停下(gdb) break exec_simple_query然后在psql里执行一条SQLGDB就会命中。技巧二查看能看到的变量命中断点后print query_string看正在处理的SQL文本。print parseTree如果是解析后的查询树能看结构体内容。bt查看当前调用堆栈这一步是理解代码执行路径的神器。技巧三条件断点缩小范围比如你只关心某张特定表的顺序扫描但又不想每次都停下来查(gdb) break seqscan if baserel-relid 16384这里的16384是表的OID可以用SQL查出来SELECT oid FROM pg_class WHERE relname your_table;技巧四调试参数持久化每次用gdb都要反复输入那些break命令太麻烦了。把断点和命令写入~/.gdbinit文件set pagination off break exec_simple_query break standard_ExecutorRun这样每次gdb启动都会自动加载。这套调试环境和GDB操作熟练之后你才算真正进入了读内核代码的状态。接下来要解决的新问题是源码这么大从哪儿开始读4. PostgreSQL源码结构地图百万行代码的先遣侦察我第一次打开PostgreSQL源码目录的时候整个人是懵的。src/下面一堆子目录每个里面又有好多文件感觉像进了一个没有路标的巨大地下停车场。后来花了一段时间才摸清规律。这个环节我想用一个地图例程的方式帮你快速建立起对源码的整体认知。你不需要背下来每个文件的名字但心里得有数遇到某个问题该去哪个目录找答案。4.1 顶层目录的势力划分PostgreSQL源码的核心全部在src/下而src/里最需要关注的是这四个目录目录内容对应关系src/backend/数据库服务端主代码几乎你能想到的所有内核机制都在这里这是研究的主战场src/include/所有的C头文件定义了各模块之间的接口和主要数据结构读代码时的字典src/common/服务端和客户端共享的工具函数比如字符串处理、错误报告辅助工具src/interfaces/各种客户端接口驱动比如libpq就是PostgreSQL的C语言客户端库研究通信协议时看而src/backend/内部重点又落在下面几个子目录postmaster/启动、监听、进程分派逻辑。postmaster.c在这里。parser/SQL词法和语法解析生成解析树。optimizer/查询优化器把解析树转换成执行计划就是EXPLAIN输出背后的逻辑。executor/执行器逐行执行计划节点并产生结果。storage/存储管理。里面又分buffer/共享缓冲池、file/文件访问、lmgr/锁管理、ipc/进程间通信。access/各种数据访问方法包括堆表heap/、索引index/、nbtree/等。catalog/系统表定义和操作。pg_class、pg_attribute这些表就是在这里定义的。commands/各类SQL命令的实现比如CREATE TABLE、VACUUM。tcop/前端和后端的交互处理最核心的postgres.c含exec_simple_query在这里。utils/各种工具包括事务管理utils/mmgr/内存上下文管理器、utils/time/、utils/snapmgr.c快照管理等。4.2 一条SQL的生命周期其实是逛遍了上述所有目录让我以一条最简单的SQL为例串起整个源码地图SELECT * FROM student WHERE age 18;这条SQL从客户端发出去到结果返回在PG源码内部会经过以下这些站点连接建立与协议解析客户端通过网络连接发送SQL文本后端进程从postmasterfork出来后PostgresMain在src/backend/tcop/postgres.c进入消息循环等待客户端指令。词法与语法解析收到SQL后调用pg_parse_query()。词法分析器扫出关键字SELECT、FROM、WHERE等语法分析器按照grammar规则构建一棵解析树Parse Tree。对应代码在src/backend/parser/。分析与重写解析树并不直接进入执行还要经过pg_analyze_and_rewrite()。这里的分析是指把表名、列名校验并转换成内部对象引用通过系统表查OID重写是指应用视图规则和触发器规则RULE。代码在src/backend/parser/analyze.c和src/backend/rewrite/。查询优化这是最核心也最复杂的阶段。pg_plan_query()调用优化器src/backend/optimizer/plan/优化器做两件事逻辑优化谓词下推、子查询提升、连接重排prep/子目录。物理优化根据统计信息估算各种执行路径的代价path/子目录选出代价最小的计划树。比如age 18这个条件如果student表上有(age)索引优化器会在顺序扫描和索引扫描之间做抉择。执行优化器生成一个计划树Plan tree执行器src/backend/executor/负责按这棵树递归执行。每执行到一个节点就调用对应的执行函数比如SeqScan对应ExecSeqScanSort对应ExecSort。执行时如果需要读取磁盘上的数据块会通过存储管理器storage/接口把数据块加载到共享缓冲池中。结果返回执行器把结果发送到客户端的网络缓冲区。整个过程你大致串一遍就能理解PG的各模块是怎么协作的。研究内核的时候无论你选哪个具体方向——锁、缓冲、WAL、索引——一定要先回到这条主链路上搞清楚你的研究对象在哪一环而不是一头扎进去读代码细节。4.3 从太浩湖到维也纳源码阅读的顺序建议面对这么大一坨代码千万别从头到尾一行行读。正确的打开方式是分层蚕食。我推荐的学习顺序是第一层摸清主循环。读PostgresMain和exec_simple_query函数搞清楚一次查询在主流程上的全局视图。这一步最简单却最能定框架。第二层理解内存上下文。PostgreSQL有一个很特别的内存管理机制——内存上下文MemoryContext。每个模块在各自的内存上下文里分配内存整块释放避免了大量malloc/free的碎片和泄漏问题。不理解内存上下文很多分配释放的代码你会看得一头雾水。第三层深入一个存储子系统。建议从共享缓冲池src/backend/storage/buffer/入手因为它是几乎所有其他子系统的基础。理解了缓冲池怎么替换、怎么和文件系统交互再去看索引和WAL会顺利很多。第四层按兴趣选择一个点深挖。比如你可以选择优化器如何估算扫描代价、WAL日志如何保证崩溃恢复、B树索引如何分裂、锁管理器如何避免死锁。选一个点用我下面要讲的方法论做一次完整的精读实验。提示读代码时一定要配合调试器。静态阅读代码时觉得理所当然的逻辑动态加断点跑一遍往往会有完全不同的理解——你会发现很多代码路径根本不会走到你预期的那支分支上去。5. 选择一个研究点深挖我推荐的三个突破口说了这么多大作业的核心还是要输出一些具体成果。很多同学的问题是库也安了环境也配了断点也能打了然后呢不知道研究什么。我根据自己的实践和见到的优秀作业总结出三个性价比最高、也最容易做出深度成果的研究方向。你根据自己的兴趣选一个就行。5.1 方向一查询优化器行为实验——为什么PG不选我建的索引这是最贴近日常数据库使用的研究方向适合对SQL调优感兴趣的同学。具体可以做的事情是创建一张百万行级别的测试表在上面建各种索引B-tree、Hash、GIN、BRIN等然后跑各种查询用EXPLAIN ANALYZE看执行计划。然后通过修改postgresql.conf里优化器相关的参数enable_seqscan、enable_indexscan、random_page_cost、cpu_tuple_cost、work_mem等观察计划的变化。内核层面的研究点在于代价模型怎么算的。阅读src/backend/optimizer/path/costsize.c搞清楚cost_seqscan和cost_index这两个关键函数的估算公式。你会发现PG的代价模型本质是IO次数估算 CPU时间估算的加权和。为什么在某些场景下PG宁可全表扫描也不用索引。答案在代价比较阶段——当表很小的时候索引扫描需要先查索引再回表两次IO不如一次顺序IO划算。这就是为什么你建了索引但查询不走索引的根本原因。做一个好的实验设计固定数据分布比如一个字段值有偏斜把random_page_cost从默认的4调到1模拟全内存场景对比执行计划的切换点。这个方向写报告也方便实验结果可以输出成图表直观清晰。5.2 方向二MVCC与快照机制实验——为什么我的事务看不到别人的修改这是PostgreSQL最引以为豪的设计之一也是理解事务隔离级别绕不开的内容。PostgreSQL的多版本并发控制MVCC原理是更新一行数据时不直接覆盖旧数据而是插入一个新版本的元组。每个元组上记录了创建它的xmin事务ID和删除它的xmax事务ID如果有的话。每个事务在开始时会获取一个快照Snapshot记录当时哪些事务已经提交、哪些还在运行。研究实验可以从这个角度切入用GDB在GetTransactionSnapshot()函数上打断点观察不同隔离级别下快照创建时机的差异读已提交是每条语句取新快照可重复读是整个事务共用一个快照。手工制造一个事务A更新一行但未提交事务B去读的场景断点停在元组可见性判断函数HeapTupleSatisfiesMVCC里逐字段查看元组头部的t_xmin和t_xmax验证可见性规则。这个方向涉及的核心代码在src/backend/access/heap/heapam_visibility.c文件不大但逻辑密集非常适合精读。5.3 方向三WAL日志与崩溃恢复实验——为什么断电后数据还在这个方向适合对可靠性、故障恢复感兴趣的同学也最贴近工业界的真实需求。PostgreSQL的WALWrite-Ahead Logging机制可以概括为一句话日志先行——数据块的修改必须先写日志且日志要落盘再写数据文件。崩溃恢复时扫描WAL日志把没来得及写入数据文件的修改重放一遍REDO再把未提交事务的修改回滚UNDO数据库就能恢复到崩溃前的某个一致状态。实验设计建议用GDB在XLogInsert函数打断点看一条UPDATE语句产生了多少条WAL记录。设置wal_levelminimal、archive_modeon触发几次检查点观察WAL段文件的数量变化。最硬核的实验写一个小C程序封装PG的XLog接口模拟写入数据页但还没刷盘的场景然后直接kill掉进程模拟掉电重启后看数据是否还在。这个实验环境做起来有一点危险可能在你的开发库上搞出不一致状态建议用单独的实例来做。这三个方向各有各的难点但共同点是都能让你在一学期内既有代码阅读又有实验数据还有报表输出。选一个别贪多。6. 实验报告写作与总结技巧如何把你的工作量讲清楚很多同学项目做得挺好实验数据一大把代码也写了上千行但最后的报告写得像流水账改分的时候特别吃亏。这里分享一些你未必能轻易在网上搜到的经验。6.1 实验报告的核心逻辑问题驱动而不是代码罗列我看过一个同学的报告标题是PostgreSQL源码分析然后从postmaster.c开始把函数一个个列出来每个函数下面粘几段注释从头堆到尾。这不能算是研究更像是目录翻译。好的报告应该围绕一个明确的问题展开。比如为什么我的表只有1000行PG却选择顺序扫描而不走索引。然后按照下面这个逻辑组织现象给出你的SQL、执行计划和实际耗时。问题提出疑问——这符合预期吗PG的逻辑是什么机制分析回到源码讲清楚优化器的代价计算逻辑配上关键函数的代码截图或伪代码。实验验证通过调整参数比如random_page_cost1.1或者改变数据分布让执行计划发生变化验证你的分析最好把变化前后的EXPLAIN ANALYZE输出放在一起对比。结论与反思总结这次研究的发现还能怎么延伸。这个结构的好处是每一部分都有明确的目的读者包括老师能一眼看出你的工作量在哪里、你的思考在哪里。6.2 让代码阅读变得可验证善用断点输出和堆栈记录报告里说我读了exec_simple_query函数太虚了你得让别人相信你真的读懂了。方法就是留证据用GDB在关键函数打断点执行SQL记录下命中断点时的堆栈bt命令输出然后把堆栈贴进报告标注每一帧对应哪个模块。在断点处print关键变量的值比如打印正在处理的查询字符串、计划树节点类型、元组可见性结果等。这些运行时数据比什么文字都更有说服力。使用xlogdumpPG自带的一些调试工具或者在WAL分析方向用的pg_waldump导出WAL日志内容展示一条UPDATE对应的WAL记录格式。总之让每一位评审看到你的结论不是从网上抄的也不是看文档脑补的而是真的在调试器里亲眼看到的。6.3 那些评审老师容易给高分的小细节根据我接触过的评分标准有几个加分项特别便宜也就是花小钱办大事画一张架构图或者时序图。比如你自己画的一条SQL从解析到执行的时序图或者共享缓冲池替换算法流程图比从书上截图的印象分高得多。做一两次对比实验。比如不同版本14 vs 16之间某个行为的差异或者PG和MySQL在某个场景下的表现对比。对比能体现你的视野。有一个自己动手改内核的小实验。哪怕你只是在某个源码文件中加了一行elog(WARNING, my debug message)或者在优化器里临时改了一个代价参数让计划翻转都比纯读代码更有实践含量。这说明你不仅会读还动了手。附录里放上你的GDB命令脚本和运行日志。很多东西写正文放不下附录是最能体现真实工作量的地方。要特别注意的雷区是千万不要写通篇都是资料综述的内容。老师见过无数个从博客和文档里拼出来的源码分析一眼就知道你在搬运。你自己动手跑出的数据、自己调的参数、自己刻的断点才是报告里最能站的住脚的部分。7. 常见问题与解药挣扎过的人才会懂的痛点最后集中回答几个我在做这类项目时高频遇到的问题每个都有血泪教训在里面。问题一GDB打断点后psql执行SQL但gdb没有反应八成是attach的进程不对。记住PostgreSQL是每个客户端连接一个进程你gdb附着的是哪个进程就得在那个进程对应的psql会话里执行SQL。我建议你用ps -ef | grep postgres列清楚所有进程用连接会话的PID来attach。问题二编译时提示Unable to determine ... on this system之类的错误这种通常是因为系统环境变量尤其是PATH、LD_LIBRARY_PATH或者缺少某些依赖。最靠谱的解法是把源码目录删了重新解压然后按我前面列的依赖逐个确认装好再重新configure。注意中间不要混装多个版本的PG装上两个版本容易把动态库路径搞乱。问题三代码改乱了跑了实验之后数据库状态不对比如你改了共享缓冲池的参数又改了一些源码逻辑结果数据库起不来或者数据错乱。最直接的办法是换个数据目录。初始化一个新数据目录initdb -D /tmp/pgtest把实验放在这个临时目录里跑怎么造都不心疼。实验做完删掉就行。反正做内核研究数据本身没什么价值浪费了也不可惜。问题四看源码分析进程和内存分配时被MemoryContext的层级搞得一头雾水说实话PG的内存上下文机制是新手最容易卡壳的地方。我的建议是先不慌着深究具体分配细节你只需要掌握内存上下文是一棵树每个模块在自己的上下文下分配内存palloc分配的内存归当前上下文管上下文重置时一次性释放这个基本概念。调试时用memory相关的\d命令或者print Mem_CXT查看当前上下文树就能对上号。等你读到了执行器的代码看到ExecutorState里那套内存上下文体系会自然理解的。如果你真要在报告里详细分析内存上下文推荐先精读src/backend/utils/mmgr/README这个文件——它是我见过的最优秀的技术文档之一讲得明明白白。问题五实验做了一半发现自己选的题目太难及时止损立刻换方向。这不是什么丢人的事内核研究是一个越深入越发现自己无知的领域选了一个自己啃不动的点还硬撑着最后只会把自己憋出内伤。建议在学期开始先做三四个小实验摸一摸各个方向的水深再定主攻方向不要在第一个实验上追求完美。这套版本选择→源码编译→调试环境配置→源码地图→方向选择→报告写作的完整方法论是我自己踩了不知道多少坑之后总结出来的。做数据库内核研究最大的敌人从来不是代码难度而是那种面对巨大源码库不知道从何下手的迷失感。希望这篇文章能帮你把那张路标地图画出来剩下的路就靠你自己用GDB的断点一步一步走出来了。
阅读完成 · 觉得有帮助?