28.5.1.5 使用堆栈跟踪

在某些 os 上,如果mysqld意外死亡,则错误日志将包含堆栈跟踪。您可以使用它来找出mysqld的死亡地点(也许是为什么)。参见第 5.4.2 节“错误日志”。要获取堆栈跟踪,不得使用-fomit-frame-pointer选项编译 gcc 的mysqld。参见第 28.5.1.1 节“编译 MySQL 以进行调试”

错误日志中的堆栈跟踪如下所示:

mysqld got signal 11;
Attempting backtrace. You can use the following information
to find out where mysqld died. If you see no messages after
this, something went terribly wrong...

stack_bottom = 0x41fd0110 thread_stack 0x40000
mysqld(my_print_stacktrace+0x32)[0x9da402]
mysqld(handle_segfault+0x28a)[0x6648e9]
/lib/libpthread.so.0[0x7f1a5af000f0]
/lib/libc.so.6(strcmp+0x2)[0x7f1a5a10f0f2]
mysqld(_Z21check_change_passwordP3THDPKcS2_Pcj+0x7c)[0x7412cb]
mysqld(_ZN16set_var_password5checkEP3THD+0xd0)[0x688354]
mysqld(_Z17sql_set_variablesP3THDP4ListI12set_var_baseE+0x68)[0x688494]
mysqld(_Z21mysql_execute_commandP3THD+0x41a0)[0x67a170]
mysqld(_Z11mysql_parseP3THDPKcjPS2_+0x282)[0x67f0ad]
mysqld(_Z16dispatch_command19enum_server_commandP3THDPcj+0xbb7[0x67fdf8]
mysqld(_Z10do_commandP3THD+0x24d)[0x6811b6]
mysqld(handle_one_connection+0x11c)[0x66e05e]

如果跟踪的函数名称解析失败,则跟踪将包含较少的信息:

mysqld got signal 11;
Attempting backtrace. You can use the following information
to find out where mysqld died. If you see no messages after
this, something went terribly wrong...

stack_bottom = 0x41fd0110 thread_stack 0x40000
[0x9da402]
[0x6648e9]
[0x7f1a5af000f0]
[0x7f1a5a10f0f2]
[0x7412cb]
[0x688354]
[0x688494]
[0x67a170]
[0x67f0ad]
[0x67fdf8]
[0x6811b6]
[0x66e05e]

在后一种情况下,可以使用resolve_stack_dumpUtil 通过以下过程来确定mysqld在何处死亡:

  • 将数字从堆栈跟踪复制到文件,例如mysqld.stack。这些数字不应包括方括号:
0x9da402
0x6648e9
0x7f1a5af000f0
0x7f1a5a10f0f2
0x7412cb
0x688354
0x688494
0x67a170
0x67f0ad
0x67fdf8
0x6811b6
0x66e05e
  • mysqld服务器创建符号文件:
shell> nm -n libexec/mysqld > /tmp/mysqld.sym

如果mysqld不是静态链接,请使用以下命令:

shell> nm -D -n libexec/mysqld > /tmp/mysqld.sym

如果要解码 C 符号,请使用--demangle(如果可用)到 nm 。如果您的 nm 版本没有此选项,则在生成堆栈转储后,需要使用 c filt 命令来分解 C 名称。

  • 执行以下命令:
shell> resolve_stack_dump -s /tmp/mysqld.sym -n mysqld.stack

如果您不能在符号文件中包含已解散的 C 名称,请使用 c filt 处理resolve_stack_dump输出:

shell> resolve_stack_dump -s /tmp/mysqld.sym -n mysqld.stack | c++filt

这会打印出mysqld死亡的地方。如果那不能帮助您找出mysqld死亡的原因,则应创建一个错误报告,并将上述命令的输出与错误报告一起包括在内。

但是,在大多数情况下,仅通过堆栈跟踪来查找问题的原因并没有帮助。为了能够定位错误或提供解决方法,在大多数情况下,我们需要知道杀死mysqld的语句(最好是杀死一个测试用例),以便我们可以重复该问题!参见第 1.7 节“如何报告错误或问题”

较新版本的glibc堆栈跟踪功能还会打印相对于对象的地址。在基于glibc的系统(Linux)上,插件内崩溃的跟踪类似于:

plugin/auth/auth_test_plugin.so(+0x9a6)[0x7ff4d11c29a6]

要将相对地址(+0x9a6)转换为文件名和行号,请使用以下命令:

shell> addr2line -fie auth_test_plugin.so 0x9a6
auth_test_plugin
mysql-trunk/plugin/auth/test_plugin.c:65

addr2line Util 是 Linux 上binutils软件包的一部分。

在 Solaris 上,过程类似。 Solaris printstack()已经打印了相对地址:

plugin/auth/auth_test_plugin.so:0x1510

要翻译,请使用以下命令:

shell> gaddr2line -fie auth_test_plugin.so 0x1510
mysql-trunk/plugin/auth/test_plugin.c:88

Windows 已经打印了地址,函数名称和行:

000007FEF07E10A4 auth_test_plugin.dll!auth_test_plugin()[test_plugin.c:72]