1. 环境准备 #
安装必要的依赖和工具:
sudo apt update
sudo apt install -y build-essential libreadline-dev zlib1g-dev flex bison libxml2-dev libxslt1-dev libssl-dev libperl-dev python3-dev tcl-dev gettext git pkg-config
验证 GCC 版本(需要 GCC 4.8 或更高版本):
gcc --version
2. 获取源码 #
下载并解压 PostgreSQL 16.4 的源码:
wget https://ftp.postgresql.org/pub/source/v16.4/postgresql-16.4.tar.gz
tar xzf postgresql-16.4.tar.gz
cd postgresql-16.4
3. 编译源码 #
配置、编译并安装 PostgreSQL:
./configure --prefix=$HOME/pgsql --enable-debug --enable-cassert CFLAGS="-O0 -g"
make -j$(nproc)
make install
4. 初始化数据库 #
创建数据目录并初始化数据库集群:
mkdir -p $HOME/pgsql/data
$HOME/pgsql/bin/initdb -D $HOME/pgsql/data
5. 启动 PostgreSQL 服务器 #
使用以下命令启动 PostgreSQL 服务器:
$HOME/pgsql/bin/pg_ctl -D $HOME/pgsql/data -l logfile start
6. 创建测试数据库和表 #
确保 PostgreSQL 服务器正在运行后,执行以下命令:
$HOME/pgsql/bin/createdb testdb
$HOME/pgsql/bin/psql testdb << EOF
CREATE TABLE test (id INT, name VARCHAR(10));
INSERT INTO test VALUES (1, 'aaa'), (2, 'bbb'), (3, 'ccc');
EOF
7. 停止 PostgreSQL 服务器 #
在开始 GDB 调试之前,停止 PostgreSQL 服务器:
$HOME/pgsql/bin/pg_ctl -D $HOME/pgsql/data stop
8. 准备 GDB 命令文件 #
创建 GDB 命令文件:
cat > gdb_commands.txt << EOF
set pagination off
set logging file gdb_output.txt
set logging enabled on
set follow-fork-mode parent
break main
break PostmasterMain
commands
silent
bt
continue
end
run
EOF
9. 使用 GDB 启动 PostgreSQL #
在终端 A 中,使用以下命令通过 GDB 启动 PostgreSQL:
gdb -x gdb_commands.txt --args $HOME/pgsql/bin/postgres -D $HOME/pgsql/data
10. GDB 中的操作和连接测试 #
-
GDB 将在
main
函数处停下。您会看到类似如下输出:Breakpoint 1, main (argc=3, argv=0x7fffffffdf98) at main.c:61 61 bool do_check_root = true;
-
此时,在终端 B 中尝试连接到数据库:
$HOME/pgsql/bin/psql -d postgres -c "SELECT version();"
此时,命令将没有任何输出,因为 PostgreSQL 服务器尚未完全启动。
-
回到终端 A 的 GDB 提示符,输入
continue
命令:(gdb) continue
-
GDB 会继续执行,直到
PostmasterMain
函数。此时,PostgreSQL 服务器应该已经完全启动。 -
此时,您应该能在终端 B 中观察到之前执行的连接命令现在已经输出了 PostgreSQL 的版本信息。
11. 进一步的 GDB 调试 #
在 GDB 提示符下,您可以设置更多断点或使用其他 GDB 命令进行调试:
(gdb) break backend_main
(gdb) continue
12. 常用 GDB 命令 #
bt
: 显示当前的调用栈frame N
: 切换到调用栈中的第 N 帧print variable_name
: 打印变量的值break function_name
: 在特定函数设置断点continue
: 继续执行程序next
: 单步执行,不进入函数step
: 单步执行,进入函数info threads
: 显示所有线程信息thread apply all bt
: 显示所有线程的调用栈
13. 结束调试会话 #
当您完成调试后,可以使用以下命令退出 GDB:
(gdb) quit
A debugging session is active.
Inferior 1 [process XXXXX] will be killed.
Quit anyway? (y or n) y
选择 ‘y’ 后,GDB 将自动终止 PostgreSQL 进程。
注意事项 #
- 调试 PostgreSQL 需要对其内部架构有一定了解。建议参考官方文档和源码注释。
- 不要在生产环境中使用启用了调试选项的 PostgreSQL 版本。
- 修改源码后,需要重新编译和安装。
- 在进行 GDB 调试之前,总是确保先停止正在运行的 PostgreSQL 实例。
这个指南涵盖了从编译 PostgreSQL 到使用 GDB 进行调试的完整过程。它提供了一个全面的工作流程,适用于 PostgreSQL 开发和调试环境。