PostgreSQL 源码级调试理解 Btree 查找

前言

话接前文从 PostgreSQL 源码深入理解 BTree 索引 - 掘金 (juejin.cn),本文首先介绍 PG 的源码安装及初始化,其次介绍 Btree 查找的源码调试,最后验证源码分析的 Btree 查找路径与源码调试的实际路径相同。

下载安装

下载

笔者使用的 Mac OS 的系统,如果读者使用其他的系统,与本文不兼容的地方请在网上查阅相关资料。下载源码。

shell 复制代码
## 从 github 下载源码
git clone git://git.postgresql.org/git/postgresql.git

## 切换到最新稳定分支
git checkout REL_16_STABLE

安装

注意下面的命令都在源码目录执行

shell 复制代码
## --prefix=/Users/XXX/dev/pghome 指定安装目录
## --enable-debug 执行需要 debug 编译
./configure --without-icu --prefix=/Users/XXX/dev/pghome --enable-debug  --enable-depend --enable-cassert

## 编译安装
make && make install

注意:编译时需要 gcc、 make 以及其他相关依赖,请结合命令报错采取相应的处理

查看安装目录

启动

首先创建 pg 启动需要的目录。注意下面的命令都在 pghome2 目录下执行。

shell 复制代码
cd pghome2
mkdir data

初始化 data 目录

shell 复制代码
./bin/initdb -D data

修改配置文件,我将端口改成 5433,因为本地有其他的 pg 服务。

bash 复制代码
vim data/postgresql.conf

启动服务

bash 复制代码
bin/pg_ctl -D data -l logfile start

初始化数据库

首先创建用户

shell 复制代码
 ## 使用./bin/createuser --help 查看所有参数
./bin/createuser -d  postgres -p 5422 -P

测试数据库来源为 demo-small-en。解压缩文件之后使用下面命令导入到数据库。

shell 复制代码
## 使用./bin/psql --help 查看所有参数
./bin/psql  -p 5433 -f demo-small-en-20170815.sql -U postgres

使用下面的命令连接到数据

bash 复制代码
./bin/psql demo_small -U postgres -p 5433

代码调试

接下来将调试 pg 源码,在正式进入调试之前,必须先了解 PG 的进程模型。

PG 进程模型

PG 采用的是多进程模型,即每一个链接对应一个进程。各个进程有不同的角色,负责不同的任务。使用 pstree 工具查看 PG 的进程。各个进程的职责可以参考 2.1. Process Architecture :: Hironobu SUZUKI @ InterDB。现在主要关注 pid 为 98759 的进程,它主要负责我们客户端连接并且执行查询工作。

也可以使用命令查询当前客户端对应的服务端进程 id

csharp 复制代码
select pg_backend_pid();

源码调试

使用 CLion: A Cross-Platform IDE for C and C++ by JetBrains 打开 PG 项目目录,使用 attach to process 功能,找目标进程。注意下文的进程号不是前文说的 98759,是因为客户端重新连接了。

接着设置一下客户端超时时间,避免由于服务端 debug 导致客户端超时。

ini 复制代码
show statement_timeout;

set statement_timeout to 6000000;

接下来以 从 PostgreSQL 源码深入理解 BTree 索引 - 掘金 (juejin.cn) 提到的查询为例。

sql 复制代码
select * from bookings where book_ref = '65BECA';

在前面的文章提到 BTree 的搜索路径为 290-> 289 -> 287,那么函数 _bt_search 的返回栈就是 287-> 289 -> 290。

在代码中打上断点,如下

在终端中运行 select * from bookings where book_ref = '65BECA';,在 CLion 中可以看到

由于 287 为叶子节点,由于下面的代码逻辑,它作为传出参数返回给调用者,并不会记录在 stack_in 参数中。

c 复制代码
// bufP 作为传出参数申明在方法签名中
*bufP = _bt_moveright(rel, heaprel, key, *bufP, (access == BT_WRITE),
                  stack_in, page_access, snapshot);
if (P_ISLEAF(opaque))
    break;

与理论分析验证

在 debug 截图中编号为 289 页 bts_offset 为 3, 编号为 290 页 bts_offset 为 2,也可以与前文理论分析内容相互验证。

下图可视化查找路径与源码调试结果相同

在编号为 289 的叶中显示得有问题,根据插件 pageinspect 显示,第一项应为 page high key,值为 CA5FE3,指向的是编号为572的页,第二项为空白值,指向的是编号为286的页。

我修复这个 bug,见 fix page high bug about parent page and report bug about leaf page by yoa1226 · Pull Request #2 · louiseGrandjonc/pageinspect_inspector (github.com)

如图在编号为 289 的叶中,参照上面图片 page high key空白 key 都正常显示。最后 Btree 的查找路径是 (290,2)-> (289,3) -> (287,?)。

总结

衔接前文,本文主要介绍了 PG 源码的安装、初始化和 BTree 查找的源码调试。

参考资料

  1. PostgreSQL: Documentation: 16: Chapter 17. Installation from Source Code

  2. clion调试postgresql - 邱明成 - 博客园 (cnblogs.com)

  3. 2.1. Process Architecture :: Hironobu SUZUKI @ InterDB

  4. louiseGrandjonc/pageinspect_inspector: A little tool to display your postgres BTree indexes in an html using pageinspect data (github.com)

相关推荐
非 白1 小时前
数据结构——树
数据结构·笔记·考研
Dizzy.5173 小时前
数据结构(查找)
数据结构·学习·算法
余衫马4 小时前
CentOS7 离线安装 Postgresql 指南
数据库·postgresql
E___V___E4 小时前
MySQL数据库入门到大蛇尚硅谷宋红康老师笔记 高级篇 part 2
数据库·笔记·mysql
m0_748254885 小时前
mysql之如何获知版本
数据库·mysql
mikey棒棒棒6 小时前
Redis——优惠券秒杀问题(分布式id、一人多单超卖、乐悲锁、CAS、分布式锁、Redisson)
数据库·redis·lua·redisson·watchdog·cas·并发锁
Asthenia04126 小时前
浏览器缓存机制深度解析:电商场景下的性能优化实践
后端
Jared_devin6 小时前
数据结构——模拟栈例题B3619
数据结构
水手胡巴7 小时前
oracle apex post接口
数据库·oracle
sushang~7 小时前
leetcode21.合并两个有序链表
数据结构·链表