postgresql中遭遇ERRORDATA_STACK_SIZE exceeded错误

在postgresql9.2中遇到一个错误,就是在流复制模式下,如果用psql访问备机,无论执行什么SQL语句,都会报ERRORDATA_STACK_SIZE exceeded错误。

网上搜了下这个错,说是因为保存错误信息的栈溢出了。在postgresql.conf中,这个值默认是2M,按理说2M足够了,因为一次错误报告没那么大。

这个值不能随便设,它与操作系统有关。在centos下,系统默认是10M。postgres里面这个值最大可以设为9.5M。

我把这个值调大了,仍然会报相同的错误。看来错误不在这里。

于是,编一个debug版的pg,然后gdb跟进去看一下。在备机启动pg后,用ps命令获取postgres进程的pid,用gdb的attach追踪这个pid。

运行psql,执行SQL语句。但是gdb却追踪不到:

因为在备机状态下,postgres会fork出子进程处理查询请求:

其中24238是备机主进程,24289是它fork出来的子进程,用来处理查询请求。

在调试的时候,你并不知道子进程的id,这个时候,gdb的一个参数就非常有用了,

 

这个follow-fork-mode可以设为两个值,child和parent,设成child就可以追踪调试进程所fork出来的子进程。

这可太方便了。

再次运行,一下子就跟到子进程中,找到了出错的函数:

罪魁祸首就是add_audit_logs,这个函数是自己加进去的,目的是用来记录一些审计信息。但是,在这个函数中会调用AssignTransactionId来得到一个新的事务id,但在备机模式下,是不允许创建事务id的:

RecoveryInProgress函数返回true,然后报错。

接着,add_audit_logs会试图记录这条错误信息,然后又获取新事务id,又引发上面这条错误。然后add_audit_logs又记录这条错误。。。

死循环了,直到存放错误信息的栈被用光,报告栈溢出。

让审计函数在备机模式下失效,就能避免此错误了。

 

posted @ 2017-07-27 14:39  sirlipeng  阅读(698)  评论(0编辑  收藏  举报