错误信息的获取途径有几种 :
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的命令行提示符.
4. gdb 所有指令 :
(gdb) help all
转载于:https://blog.51cto.com/zalax303/926835