错误信息的获取途径有几种 : 
1. 最简单的就是看PostgreSQL的log文件.
2. 在PostgreSQL中可以使用psql的 \set VERBOSITY verbose 来输出详细的错误信息, 
3. 或者使用linux的strace跟踪这个发生错误的进程.
4. 使用gdb (GNU Debugger) 来调试则是一种比较深入但是非常有用的工具.
下面就以前面我在使用pgsql_fdw时遇到的问题使用gdb来做个简单的演示 : 
要让postgresql能够使用gdb进行调试, 首先要在编译PostgreSQL时打开enable-debug.
例如, 使用如下方法编译 : 
 
   

 

./configure --prefix=/home/digoal/pgsql91 --with-pgport=1999 --with-perl --with-python --with-openssl --with-pam --without-ldap --with-libxml --with-libxslt --enable-thread-safety --with-wal-blocksize=16 --enable-debug && gmake world
sudo gmake install-world

 


 
在满足这个条件后, 初始化数据库
 
   

initdb -D $PGDATA -E UTF8 --locale=C -W -U postgres

使用gdb进行调试 : 
会话1 : 
获取当前进程的pid.
 
   

 

digoal@db-172-16-3-33-> psql postgres postgres
psql (9.1.3)
Type "help" for help.

postgres=# select pg_backend_pid();
 pg_backend_pid 
----------------
          26841
(1 row)

postgres=# \set VERBOSITY verbose

 


 
会话2 : 
使用gdb, 绑定到会话1获取到的进程PID.
 
   

 

digoal@db-172-16-3-33-> gdb
(gdb) attach 26841

 

在出错的函数处设置断点(b getTypeOutputInfo) : 
 
   

 

(gdb) b getTypeOutputInfo
Breakpoint 1 at 0x6cbaf0: file lsyscache.c, line 2434.

 


 
会话1 : 
执行那个报错的函数 : 
 
   

postgres=select f_test();


会话2 : 
继续执行(c), 跟踪到 getTypeOutputInfo的输入参数如下 : 
 
   

 

(gdb) c
Continuing.
Breakpoint 1, getTypeOutputInfo (type=0, typOutput=0x7fff1c55df58, typIsVarlena=0x7fff1c55df5f "") at lsyscache.c:2434
2434    {

 

查看截止到断点前的所有调用(bt或backtrace) : 
注意这里的结果和实际的调用顺序是反的, 如, #1的execute_query调用了#0的 getTypeOutputInfo
 
   

 

(gdb) bt
#0  getTypeOutputInfo (type=0, typOutput=0x7fff1c55df58, typIsVarlena=0x7fff1c55df5f "") at lsyscache.c:2434
#1  0x00002b066328943b in execute_query (node=0x17f14c70) at pgsql_fdw.c:668
#2  0x00002b066328a00f in pgsqlIterateForeignScan (node=0x0) at pgsql_fdw.c:352
#3  0x0000000000573a6f in ForeignNext (node=0x0) at nodeForeignscan.c:49
#4  0x0000000000560b1e in ExecScanFetch (node=0x17f14c70, accessMtd=0x573a30 <ForeignNext>, recheckMtd=0x5738b0 <ForeignRecheck>)
    at execScan.c:82
#5  ExecScan (node=0x17f14c70, accessMtd=0x573a30 <ForeignNext>, recheckMtd=0x5738b0 <ForeignRecheck>) at execScan.c:167
#6  0x0000000000559dda in ExecProcNode (node=0x17f14c70) at execProcnode.c:432
#7  0x000000000056b5c8 in ExecLimit (node=0x17f14970) at nodeLimit.c:91
#8  0x0000000000559eaa in ExecProcNode (node=0x17f14970) at execProcnode.c:490
#9  0x0000000000558d21 in ExecutePlan (queryDesc=0x17f12850, direction=475389784, count=0) at execMain.c:1439
#10 standard_ExecutorRun (queryDesc=0x17f12850, direction=475389784, count=0) at execMain.c:313
#11 0x00000000005788a3 in _SPI_execute_plan (plan=0x17f16870, paramLI=0x17e0ae68, snapshot=<value optimized out>, 
    crosscheck_snapshot=0x0, read_only=0 '\000', fire_triggers=1 '\001', tcount=0) at spi.c:2110
#12 0x0000000000578c9d in SPI_execute_plan_with_paramlist (plan=0x17f16870, params=0x17e0ae68, read_only=0 '\000', tcount=0)
    at spi.c:423
#13 0x00002b0663072133 in exec_run_select (estate=0x7fff1c55e580, expr=0x17f0c880, maxtuples=0, portalP=0x0) at pl_exec.c:4580
#14 0x00002b0663075809 in exec_stmt (estate=0x7fff1c55e580, stmts=<value optimized out>) at pl_exec.c:1413
#15 exec_stmts (estate=0x7fff1c55e580, stmts=<value optimized out>) at pl_exec.c:1248
#16 0x00002b0663075628 in exec_stmt_block (estate=0x7fff1c55e580, block=0x17f0cb40) at pl_exec.c:1186
#17 0x00002b0663078273 in plpgsql_exec_function (func=0x17eee148, fcinfo=0x17f18940) at pl_exec.c:324
#18 0x00002b066306d3e3 in plpgsql_call_handler (fcinfo=0x17f18940) at pl_handler.c:122
#19 0x000000000055d5be in ExecMakeFunctionResult (fcache=0x17f188d0, econtext=0x17f186e0, isNull=0x17f19258 "\024", 
    isDone=0x17f19370) at execQual.c:1824
#20 0x000000000055a35a in ExecTargetList (projInfo=<value optimized out>, isDone=0x7fff1c55e92c) at execQual.c:5104
#21 ExecProject (projInfo=<value optimized out>, isDone=0x7fff1c55e92c) at execQual.c:5319
#22 0x000000000056fcd3 in ExecResult (node=0x17f185d0) at nodeResult.c:155
#23 0x0000000000559d06 in ExecProcNode (node=0x17f185d0) at execProcnode.c:367
#24 0x0000000000558d21 in ExecutePlan (queryDesc=0x17ebbfa0, direction=475389784, count=0) at execMain.c:1439
#25 standard_ExecutorRun (queryDesc=0x17ebbfa0, direction=475389784, count=0) at execMain.c:313
#26 0x000000000061d9d4 in PortalRunSelect (portal=0x17eb9f90, forward=<value optimized out>, count=0, dest=0x17eb0050)
    at pquery.c:943
#27 0x000000000061eee0 in PortalRun (portal=0x17eb9f90, count=9223372036854775807, isTopLevel=1 '\001', dest=0x17eb0050, 
    altdest=0x17eb0050, completionTag=0x7fff1c55eb90 "") at pquery.c:787
#28 0x000000000061bbbb in exec_simple_query (query_string=0x17eae9c0 "select f_test();") at postgres.c:1018
#29 0x000000000061c3c4 in PostgresMain (argc=<value optimized out>, argv=<value optimized out>, username=<value optimized out>)
    at postgres.c:3926
#30 0x00000000005e191b in ServerLoop () at postmaster.c:3606
#31 0x00000000005e253c in PostmasterMain (argc=1, argv=0x17e05090) at postmaster.c:1116
---Type <return> to continue, or q <return> to quit--- 
#32 0x0000000000586d6e in main (argc=1, argv=<value optimized out>) at main.c:199

 

其他常用gdb指令 : 
print
next
nexti

【参考】

1. (gdb) 是gdb的命令行提示符.