分享MySQL常用 内核 Debug 几种常见方法


Posted in MySQL onMarch 17, 2022

阅读本文你将了解:

  • 如何准备 MySQL 调试环境
  • GDB 调试入门及操作示例
  • Trace 文件调试及操作示例

一、准备 Debug 环境

首先用源码编译安装一个用来调试的 MySQL 环境。

开启-DWITH_DEBUG ,在源码路径创建 build 目录,

进入目录并执行:

cmake .. -DWITH_BOOST=../../boost -DWITH_DEBUG=1

然后通过如下方式,确认是否编译成功。

方式一:

$ ./bin/mysqld --verbose --version

回显 debug 版本信息,则编译的是 debug 版本。

ver 8.0.18-debug for Linux on x86_64 (Source distribution)

方式二:

连接数据库,执行查看版本命令。回显包含了 debug 字样,则编译的是 debug 版本。

$ mysql> select version();
+--------------+
| version()    |
+--------------+
| 8.0.18-debug |
+--------------+
1 row in set (0.00 sec)

二、使用 GDB 调试

GDB 全称 “GNU symbolic debugger”,是 Linux 下常用的程序调试器,通常以 gdb 命令的形式在终端(Shell)中使用。

启动 GDB 编译器

执行如下命令启动 GDB 编译器(假设 my.cnf 在用户根目录中)。进入 GDB 后,敲入 run 即可运行。

gdb --args ./bin/mysqld --defaults-file=~/my.cnf --gdb

其中 --gdb 参数允许你随时 Ctrl+C 的方式中断 mysqld 进程,进行调试命令。

GDB 常用命令

使用多窗口查看源码与调试的读者,可以使用 layout 命令,在 gdb 中执行help layout 可以查看更多 gdb 命令用法。

(gdb) help layout
(gdb) help layoutChange the layout of windows.
Usage: layout prev | next | <layout_name>
Layout names are:
   src   : Displays source and command windows.
   asm   : Displays disassembly and command windows.
   split : Displays source, disassembly and command windows.
   regs  : Displays register window. If existing layout
           is source/command or assembly/command, the
           register window is displayed. If the
           source/assembly/command (split) is displayed,
           the register window is displayed with
           the window that has current logical focus.
           (gdb)

Debug 示例

安装好 Debug 环境后,我们用以下两个例子,来简单演示使用思路及技巧。

1、取变量值

在某种情况下发现 mysqld 已经 crash,系统只有一个 core 文件,而我们要知道某个系统变量的值。但是系统变量的值,不见得与 my.cnf 文件一致。

此时,就可以用 gdb 命令将变量打印出来,获取变量值。

如下所示,需获取变量 version 的值,只需要在前面加mysql_sysvar_ 前缀打印即可。

Thread 1 "mysqld" received signal SIGINT, Interrupt.
0x00007ffff5f74cb9 in __GI___poll (fds=0x55555e8a3de0, nfds=2, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:29
29    ../sysdeps/unix/sysv/linux/poll.c: No such file or directory.
(gdb) p mysql_sysvar_version
$1 = {flags = 68101, name = 0x55555e7ff738 "innodb_version", comment = 0x55555ca953e2 "InnoDB version", check = 0x555558e222f1 <check_func_str(THD*, SYS_VAR*, void*, st_mysql_value*)>, update = 0x555558e22881 <update_func_str(THD*, SYS_VAR*, void*, void const*)>,
  value = 0x55555def1c20 <innodb_version_str>, def_val = 0x55555ca89598 "8.0.18"}
(gdb)

2、调试脚本

假设需获取某一个连接进入dispatch_command 有哪些 command ,可以执行 gdb 脚本[2] 获取。

gdb 脚本内容如下:

b dispatch_command
commands
    print command
    continue
end

执行 gdb 脚本,然后使用 mysql 客户端连接数据库,并执行 SQL 语句操作,即可查看到 gdb 调试信息。

(gdb) b dispatch_command
Breakpoint 3 at 0x555558ddb37c: file /home/kyc/mysql8/sql/sql_parse.cc, line 1581.
(gdb) commands
Type commands for breakpoint(s) 3, one per line.
End with a line saying just "end".
>print command
>continue
>end
(gdb) c
Continuing.
[Switching to Thread 0x7fffe01fc700 (LWP 5941)]

Thread 49 "mysqld" hit Breakpoint 3, dispatch_command (thd=0x7fff4c000f70, com_data=0x7fffe01fbba0, command=COM_QUERY) at /home/kyc/galaxyengine/sql/sql_parse.cc:1581
1581                          enum enum_server_command command) {
$4 = COM_QUERY

三、使用 Trace 文件调试

MySQL 的 debug 版提供了一个专门的 DBUG 包[3]。通过这个 DBUG 包,可获取正在执行操作程序的 Trace 文件。

通过控制 DBUG 开关,可以将 MySQL 的任何操作,以及所涉及的调用模块、函数、状态信息记录在 Trace 文件中。

设置 debug 参数

通过设置 debug 参数选项,指定跟踪方式。

--debug [ = debug_options ]

[ = debug _ options ] 可识别字符 d、t、i 、o 等。

Debug 示例

若需获取代码中DBUG_PRINT("info:" 打印的日志,可以使用 MySQL 客户端连上服务器,并执行如下命令,开启 debug 参数。

set debug = 'd,info';
use test;

mysqld.trace 文件,可获取 use test 在 MySQL 中的执行流程。

do_command: info: Command on socket (46) = 3 (Query)
do_command: info: packet: '                 '; command: 3
dispatch_command: info: command: 3
gtid_pre_statement_checks: info: gtid_next->type=0 owned_gtid.{sidno,gno}={0,0}
THD::is_ddl_gtid_compatible: info: SQLCOM_CREATE:0 CREATE-TMP:0 SELECT:1 SQLCOM_DROP:0 DROP-TMP:0 trx:0
SELECT_LEX::prepare: info: setup_ref_array this 0x7fff1400d298    3 :    0    0    1    2    0    0
setup_fields: info: thd->mark_used_columns: 1
setup_fields: info: thd->mark_used_columns: 1
SELECT_LEX::setup_conds: info: thd->mark_used_columns: 1
THD::decide_logging_format: info: query: SELECT DATABASE()
THD::decide_logging_format: info: variables.binlog_format: 2
................
MDL_context::release_locks_stored_before: info: found lock to release ticket=0x7fff14019ae0
MDL_context::release_locks_stored_before: info: found lock to release ticket=0x7fff1412dd20
MDL_context::release_locks_stored_before: info: found lock to release ticket=0x7fff1412dcc0
net_send_ok: info: affected_rows: 0  id: 0  status: 2  warning_count: 0
net_send_ok: info: OK sent, so no more error sending allowed

本文使用几个简单的示例,演示了 MySQL 内核的 Debug 的几种常见方法。当然,仅仅起到抛砖引玉的作用,更多好玩的技巧,还需读者自行深度挖掘。

参考:

[2]: GDB 脚本调试:https://sourceware.org/gdb/current/onlinedocs/gdb/Commands.html#Commands

[3]: DBUG Package[:https://dev.mysql.com/doc/refman/8.0/en/dbug-package.html

MySQL 相关文章推荐
浅谈Mysql多表连接查询的执行细节
Apr 24 MySQL
浅谈MySQL user权限表
Jun 18 MySQL
分析mysql中一条SQL查询语句是如何执行的
Jun 21 MySQL
MySQL8.0.18配置多主一从
Jun 21 MySQL
SQL实现LeetCode(178.分数排行)
Aug 04 MySQL
深入解析MySQL索引数据结构
Oct 16 MySQL
为什么MySQL 删除表数据 磁盘空间还一直被占用
Oct 16 MySQL
Mysql关于数据库是否应该使用外键约束详解说明
Oct 24 MySQL
一文带你探究MySQL中的NULL
Nov 11 MySQL
SQL注入篇学习之盲注/宽字节注入
Mar 03 MySQL
MySQL分区以及建索引的方法总结
Apr 13 MySQL
详解Mysql事务并发(脏读、不可重复读、幻读)
Apr 29 MySQL
MySQL如何快速创建800w条测试数据表
Mar 17 #MySQL
利用JuiceFS使MySQL 备份验证性能提升 10 倍
MySQL 分区表中分区键为什么必须是主键的一部分
MySQL优化及索引解析
一条 SQL 语句执行过程
Mysql事务索引知识汇总
Mar 17 #MySQL
MySQL慢查询优化解决问题
Mar 17 #MySQL
You might like
php学习之简单计算器实现代码
2011/06/09 PHP
PHP CodeBase:将时间显示为&quot;刚刚&quot;&quot;n分钟/小时前&quot;的方法详解
2013/06/06 PHP
PHP中CURL的CURLOPT_POSTFIELDS参数使用细节
2014/03/17 PHP
函数中使用require_once问题深入探讨 优雅的配置文件定义方法推荐
2014/07/02 PHP
php实现将任意进制数转换成10进制的方法
2015/04/17 PHP
laravel 实现划分admin和home 模块分组
2019/10/15 PHP
jQuery选择头像并实时显示的代码
2010/06/27 Javascript
jQuery之$(document).ready()使用介绍
2012/04/05 Javascript
JavaScript高级程序设计(第3版)学习笔记3 js简单数据类型
2012/10/11 Javascript
js this函数调用无需再次抓获id,name或标签名
2014/03/03 Javascript
js实现同一个页面多个渐变效果的方法
2015/04/10 Javascript
WebGL利用FBO完成立方体贴图效果完整实例(附demo源码下载)
2016/01/26 Javascript
让你一句话理解闭包(简单易懂)
2016/06/03 Javascript
详解如何在Vue2中实现组件props双向绑定
2017/03/29 Javascript
微信小程序城市定位的实现实例(获取当前所在国家城市信息)
2017/05/17 Javascript
JS库particles.js创建超炫背景粒子插件(附源码下载)
2017/09/13 Javascript
Vue的生命周期操作示例
2019/09/17 Javascript
vue 输入电话号码自动按3-4-4分割功能的实现代码
2020/04/30 Javascript
Python操作Excel之xlsx文件
2017/03/24 Python
浅谈flask中的before_request与after_request
2018/01/20 Python
Python使用matplotlib简单绘图示例
2018/02/01 Python
Window10+Python3.5安装opencv的教程推荐
2018/04/02 Python
Python+OpenCV目标跟踪实现基本的运动检测
2018/07/10 Python
Sanic框架请求与响应实例分析
2018/07/16 Python
详解python中的lambda与sorted函数
2020/09/04 Python
CSS3中的opacity属性使用教程
2015/08/19 HTML / CSS
HTML5之SVG 2D入门11—用户交互性(动画)介绍及应用
2013/01/30 HTML / CSS
HTML最新标准HTML5总结(必看)
2016/06/13 HTML / CSS
印尼最大的婴儿用品购物网站:Orami
2017/09/28 全球购物
八年级英语教学反思
2014/01/09 职场文书
高中体育教学反思
2014/01/24 职场文书
结婚周年感言
2014/02/24 职场文书
党员个人公开承诺书
2014/08/29 职场文书
公安民警正风肃纪剖析材料
2014/10/10 职场文书
大学生党员批评与自我批评范文
2014/10/14 职场文书
python绘制云雨图raincloud plot
2022/08/05 Python