使用 windbg.exe 调试 PostgreSQL

来自 PostgreSQL wiki
跳转到导航跳转到搜索

获取在 Windows 上运行的 PostgreSQL 后端的堆栈跟踪 移动,因为 windbg.exe 不是明智的人在有 VS Express 版本的情况下使用的工具。

使用 WinDBG 获取堆栈跟踪

Windows 调试工具包含一个名为 windbg.exe 的程序,即 Windows 调试器。它是一个非常强大和有用的工具,但它不是用户友好的。Windbg.exe 也可以用来远程调试系统,即使你没有完整的 GUI 访问权限。使用 windbg 可能会中断后端的执行,或者可能(尽管不太可能)甚至在目标后端暂停时阻塞整个数据库系统。

你需要知道要连接的后端的进程 ID。有关如何找到进程 ID,请参见上面的“获取 PostgreSQL 后端的进程 ID”。

一旦知道进程 ID,你需要启动 WinDBG。它将位于 Windows 调试工具的“开始”菜单中。要连接到目标 PostgreSQL 后端,请使用“文件”->“附加到进程”菜单项(快捷键:F6)。将你之前找到的 pid 输入“进程 ID”字段,然后按回车键。

windbg 现在已附加到该 postgres 后端。它的执行已暂停,并且看起来好像挂起。这是正常的。你处于命令行界面。这些说明将提供你需要的基本步骤,更多信息可以在了解有关 windbg 的更多信息部分找到。

首先,输入“G”(不带引号)并按回车键。这将导致你附加到的后端取消暂停并恢复正常执行。调试器保持附加状态,并将捕获崩溃或其他异常事件,你也可以手动暂停它。在附加但未暂停的情况下,调试器不会影响该 PostgreSQL 后端的正常运行。

首先,你应该在后端正常运行时获取其堆栈跟踪,并确保堆栈跟踪有效且有用。收集一堆最终结果不完整且无用的堆栈跟踪是毫无意义的。

获取正常运行的后端的堆栈跟踪

出于测试目的,或者因为你想查看后端在忙什么,你可能想获取正常运行的后端的堆栈跟踪。这不会提供有关崩溃的信息;有关崩溃信息,请参见后面的部分。

首先,使用“调试”菜单中的“中断”命令中断执行。这将返回你到命令行。

现在输入以下命令

~*k

并按回车键,然后选择所有输出(CTRL-A)并将其复制(CTRL-C)到剪贴板。你现在可以将这些信息粘贴到文本文件、电子邮件等中。它看起来像这样

   0  Id: b0c.b1c Suspend: 1 Teb: 7ffdf000 Unfrozen
ChildEBP RetAddr  
00cafc2c 7c90df5a ntdll!KiFastSystemCallRet
00cafc30 7c8025db ntdll!ZwWaitForSingleObject+0xc
00cafc94 7c802542 kernel32!WaitForSingleObjectEx+0xa8
00cafca8 00587866 kernel32!WaitForSingleObject+0x12
00cafcb4 0058ba4c postgres!pg_usleep+0x36 [c:\pginstaller-repo\postgres.windows\src\backend\port\win32\signal.c @ 56]
00cafd18 00596075 postgres!AutoVacLauncherMain+0x24c [c:\pginstaller-repo\postgres.windows\src\backend\postmaster\autovacuum.c @ 597]
00caff60 00502da7 postgres!SubPostmasterMain+0x2b5 [c:\pginstaller-repo\postgres.windows\src\backend\postmaster\postmaster.c @ 3900]
00caff7c 006b7aad postgres!main+0x177 [c:\pginstaller-repo\postgres.windows\src\backend\main\main.c @ 165]
00caffc0 7c817027 postgres!__tmainCRTStartup+0x10f [f:\sp\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 597]
00cafff0 00000000 kernel32!BaseProcessStart+0x23

   1  Id: b0c.95c Suspend: 1 Teb: 7ffde000 Unfrozen
ChildEBP RetAddr  
0162fecc 7c90d3aa ntdll!KiFastSystemCallRet
0162fed0 7c83145e ntdll!ZwFsControlFile+0xc
0162ff14 0058777f kernel32!ConnectNamedPipe+0x52
0162ffb4 7c80b6d9 postgres!pg_signal_thread+0x9f [c:\pginstaller-repo\postgres.windows\src\backend\port\win32\signal.c @ 275]
0162ffec 00000000 kernel32!BaseThreadStart+0x37

#  2  Id: b0c.208 Suspend: 1 Teb: 7ffdc000 Unfrozen
ChildEBP RetAddr  
0163ffc8 7c951e68 ntdll!DbgBreakPoint
0163fff4 00000000 ntdll!DbgUiRemoteBreakin+0x2d

如果你已经收集了所有需要的东西,你可以从 PostgreSQL 进程中分离(调试菜单 -> 分离被调试者)并关闭 WinDBG。或者,如果你想在执行的不同点收集更多堆栈跟踪,请使用“G”命令告诉 PostgreSQL 继续运行。当你想再次中断它时,使用“调试”菜单中的“中断”命令,并输入 ~*k 获取另一组堆栈跟踪。


获取可重复的后端崩溃的堆栈跟踪

如果你正在尝试追踪后端崩溃,并且可以在你选择的连接中合理地预测崩溃,你可能想使用 windbg。你需要在后端仍在运行时将 windbg 附加到它(见上文),并在 windbg 中发出“G”命令让后端继续运行。现在,你需要使用与后端的连接执行触发崩溃所需的操作。

当后端崩溃时,windbg 应该会中断崩溃。此时,你可以在 windbg 中运行以下命令以获取有关崩溃的一些堆栈跟踪信息

~*k

postmaster 启动期间的崩溃

这篇关于调试 Windows 服务的有用文章 将帮助你处理 postmaster 在启动 PostgreSQL 的 Windows 服务期间崩溃的问题。

使用 windbg.exe 进行远程调试

你可能不想或无法在数据库服务器控制台中进行调试。但这不会阻止你使用 windbg 调试 PostgreSQL - 你可以在 Pg 计算机上启动一个远程调试服务器,并从另一台计算机进行调试,甚至可以通过互联网进行调试。 Visual Studio 也支持远程调试.

  • 在 Pg 服务器上
    • dbgsrv.exe 从 Windows 调试工具文件夹复制到运行 Pg 的远程服务器(或在那里安装调试工具)。
    • 在远程计算机的防火墙中添加 dbgsrv.exe 的例外。
    • 以管理员身份在远程计算机上启动 dbgsrv.exe。使用以下命令:dbgsrv.exe -t tcp:port=12345,password=fred。(如果需要,请使用 runas.exe 获取管理员权限)。
  • 在你正在进行调试的工作站上
    • 启动 windbg
    • 在“文件”菜单中,选择“连接到远程存根...”
    • 作为连接字符串,输入“tcp:server=YOUR_PG_SERVER_NAME_OR_IP,port=12345,password=fred”
    • 点击“确定”
    • Windbg 现在将尝试通过远程调试存根执行所有工作,就像你在该计算机上运行 windbg 一样,因此你可以按照上面给出的说明进行操作。

了解有关 windbg 的更多信息

如果你想了解有关使用 windbg 的更多信息,这篇文章 是一个很好的起点。

如果你熟悉 gdb,你可能还想阅读 这篇文章关于 WinDBG 用户的 gdb,如果你要反过来也是非常方便的。

可以在 [windbg 命令摘要](http://windbg.info/doc/1-common-cmds.html) 中找到有关 windbg 的更多指导。