暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Postgres内核代码100万行,怎么读?

我们今天请到张明礼 (Zhang Mingli) 老师分享他的内核开发经验。
张老师在2024年10月被PG官方社区评选成为 PostgreSQL Contributor。曾在Greenplum Team工作,也是 Apache Cloudberry 的主要commiter之一。
第三位中国成员!CloudberryDB 核心开发者张明礼入选 PostgreSQL Contributor 名单
PostgreSQL全球开发组公布 “New PostgreSQL Contributors”


和大部分初学者一样,我也是从对Postgres一无所知开始的,我刚入职Greenplum的时候,甚至没听过PostgreSQL数据库。幸运的是,Greenlum的同事们水平很高,我从他们身上学习到了很多。我也跟朋友们聊过学习内核的方法,他们每一个的方法都不相同,但个个都成了独当几面的大佬,结合他们的经验以及自己的亲身经历,谈谈如何从小白成为内核开发专家。
首先要说明的是,Postgres是一个复杂的系统,你不可能一下就掌握所有领域。
Postgres 17 代码统计:仅看 h, c文件,大约有121万行。
而我们的工作主要是在Postgres基础之上,开发Greenplum/Cloudberry分布式数据库。Greenplum/Cloudberry 代码统计:h, c 文件大约有159万行,c++文件18万行(这里大部分应该是ORCA优化器的代码)
159万行代码,就算去掉一些同质化的代码,内核涉及到的代码也大概会在100万之上。
某Y公司CEO对我说过:“数据库,在某种程度上比操作系统还要复杂些”。
对于一个工业级的软件,一个人是不可能掌握全部的。一个切实可行的目标是:对Postgres各个领域有一个 “中等” 程度的了解,并且重点掌握其中的一个或几个领域。我的leader曾对我说:“就算每天能读500-1000行代码,全部记得住,理解且不忘掉,可以计算下要多久才能读完一遍。”
刚开始的时候,我也看过一些文章,介绍如何学习Postgres内核,比如看一些数据库的书籍,论文,github上一些关于Postgres的总结,CMU 的某些课程,数据库的架构等等。但是经过实践经验,这些对我的用处不是太大,甚至我觉得初学者可以完全跳过,等到水平达到一定程度再结合实际代码进行交叉验证学习。
这些知识当然是有些用的,如果用来了解学习,完全没问题。但是对于要开发内核来说,光看是没用的。数据库的理论发展的比较完全,难在实际的工程实践。理论好比武功心法,即使背的滚瓜烂熟,却连一个招式都不会,很可能谈起数据库理论头头是道,也可能遇到一个bug完全不知从何下手。
既然要做内核开发,与其迂回,不如直入主题。我的方法主要就是,阅读、调试代码。这可能是最难,也是最简单的方法。
数据库是一个系统性工程,阅读代码需要了解一些基础知识:
  • C语言(不要求精通,但要有一定程度的了解)
  • 操作系统 (需要一定程度的了解,进程架构,共享内存,信号处理等)
  • 数据库系统知识 (可以在业余时间看看)
  • SQL (了解常用的,命令太多,可以边做边学)
  • Postgres 基础架构(围绕官网这张图大致了解)

上面的基础,不用精通,可以边做边学。他们不是依赖关系,比如Postgres其实也是个很好的C语言教程,学习内核的一部分其实也会学习操作系统。
关于论文:我的经验是是不建议初学者研读,理由和上面一样,在没有任何内核开发经验的时候读论文,会有点虚无缥缈,对于初学者,脚踏实地更重要。
关于Postgres基础架构,推荐网站:The Internals of PostgreSQL(https://www.interdb.jp/pg/index.html)。了解下里边的内容我觉得就差不多了,网站的图做的很好,很多文章也是直接用的他们的图。
为什么我觉得架构稍微了解下就好?Greenplum Tech Lead曾经对我说:
“只谈架构,毫无意义,必须一个一个case地去优化。”
我深表同意,架构就几句话,几张图,谁都可以谈,甚至在面试时的校招生也会侃侃而谈架构如何。但要是从事内核开发,必须要深入代码具体实践才行。
当对上面有一个大致了解后,可以选一个领域进行深入研究。根据上次投票的结果,大家对优化器的热情最高。但是以我的经验,如果完全是初学者,建议从存储开始看起。
某大佬曾经对我说:
“如果不看存储,很多时候你根本不知道内核在做什么。”
存储是数据库的底座,优化器是建立在存储之上的,如果没有对存储的了解,优化器就有点空中楼阁了。
可以从一个很简单的例子开始,当年我的leader曾经建议:比如在数据库中执行一下下面SQL,看看背后都发生了什么。
    select * from t; 
    我们可以先调试Postgres的Heap表,有一定经验之后可以调试一下Greenplum/Cloudberry的AO/AOCS表。用GDB打一些断点,比如SeqScan前后的的函数,看看数据是如何一步一步从磁盘到内存,里面经过了哪些处理和优化的等等。
    这个时候就要精读代码了,不要求每个细节全都掌握,但是泛泛地看,意义不大。具体的程度怎么把握也是个经验,可以看看X老师此前的文章:
    Postgres内核面试:位图集合(Bitmapset)如何实现?
    对于某一个函数或者知识的了解程度,比上面文章的例子稍微降低一些即可。 刚开始接触内核,代码就像一个巨大的科技树,每个函数都深入研究,会让初学者陷入到一个黑洞,看着看着就迷失了。
    在阅读代码的同时,可以结合具体的例子进行开发。一个很好的实践是:看看开源社区有哪些相关的issue,比如 Cloudberry (https://github.com/apache/cloudberry/issues) 打着good first issue标签的,一般都比较简单,非常适合初学者进行学习。通过修复bug,逐渐积累自信心,不断鼓励自己。
    还可以找一个Pull Requset,从review别人的代码做起。当然一开始会有很多不理解,可以拿出一定的时间,围绕这个pull request,想想作者为什么这么改代码,有没有更好的办法,围绕着问题的点,画一个圆,把涉及到的周边知识都学习一下。
    经过了一阵痛苦时期,慢慢的你对内核代码逐渐了解,看代码也可以做到一目十行了。这个时候,就可以根据自己的兴趣,寻找下一个领域,点亮更多的科技树。
    PostgreSQL 内核五大领域
    对Postgres内核有一定程度了解之后,可以关注Greenplum/Cloudberry额外的代码部分,重点围绕单机数据库与分布式数据库的区别。比如分布式计划如何生成,Slice, Gang, Motion等概念与Postgres单机计划的对比。分布式Join的相容性等等。
    这个阶段保持持续的学习,慢慢的你会不自觉的更上一层楼。即使对于不那么熟悉的模块,由于前面打下的基础,以及对于内核潜移默化的了解,出现问题的时候也能水到渠成的解决。
    当积累了一定经验知识,还要勇于实践。对于内核开发,展现水平的是你的输出。多跟社区交流,修复bug,review别人的代码 。从浅入深,可以尝试去做一个小feature,再到比较大的涉及面广的feature等等。慢慢的你会成为擅长某个模块的专家,对于这个模块的问题,能迅速的定位,修复。当对于某个模块有着深入的了解后,别人可能需要几天,几星期才能修复的bug,你一天甚至一个小时就可以搞定了。
    “数据库到后面就是越来越简单” -- 也是某大佬说的~~
    还有一个感觉是:看了那么多代码,我们能都记得住吗,都真正的理解了吗?我的答案是:绝知此事要躬行。
    一个知识,当时记住了,过了一年半载不一定能记得那么清晰。而如果你彻底的理解了,修复过这个知识相关的bug,或者做了基于此的feature,无论过了多久,稍加回忆,基本都会记得细节。
    举一个我自己的例子,大概两年前我们将Greenplum 7(Postgres 12内核)升级到Postgres 14内核,由此诞生了Cloudberry。在做快照snapshot升级的时候,版本差异特别大,且Greenplum是分布式数据库,还需要考虑分布式快照与Postgres14的结合问题。
    彼时的我对Greenplum分布式快照还不是很了解,就花了大概两周的时间,将分布式事务相关的代码都看了一遍,结果发现Greenplum 分布式事务相关有很多问题可以优化,给GPDB社区提了一个commit:

    这个commit 修复的问题包括:分布式事务, 分布式快照,dlog, MVCC,原子操作TAS, CAS 等,代码改动不大,GPDB已经闭源,Pull Requset看不到了,有兴趣可以看看commit:
    https://github.com/greenplum-db/gpdb-archive/commit/87fbf064ba231e6bde03bdbb1c07af0adcbdc22f
    其实这里面,一个是6个修复,可惜最关键的一个没有被merge到Greenplum 主分支,即:在32位的操作系统上,GPDB的分布式事务ID不能保证是一个原子操作。
    是的,GPDB 可能在32位系统上无法保证ACID,幸运的是我们在Cloudberry上修复了这个问题。
    不仅是我,身边同事也有类似的经历:比如就找一个最难的bug,围绕着上上下下的研究学习,最后bug修复了,也就基本上了解了很多知识,从此如鱼得水。
    千里之行,始于足下。内核开发是一场马拉松,开始的磕磕绊绊都无所谓。我的leader曾告诉我:“只争朝夕”,与君共勉。

    文章转载自开源软件联盟PostgreSQL分会,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

    评论

    金小仓
    暂无图片
    关注
    暂无图片
    获得了901次点赞
    暂无图片
    内容获得606次评论
    暂无图片
    获得了351次收藏