工具 | 常用 MySQL 内核 Debug 技巧

作者:柯煜昌 顾问软件工程师
目前从事 RadonDB MySQL 容器化研发,华中科技大学研究生毕业,有多年的数据库内核开发经验。

掌握 MySQL 内核源码的阅读和调试能力,不仅是数据库研发人员的日常,也是 DBA 进阶的必经之路。

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

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

开启 -DWITH_DEBUG ,在源码路径创建 build 目录,进入目录并执行:

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

然后通过执行以下操作确认编译是否成功。

[En]

Then confirm whether the compilation is successful by doing the following.

方式一:

$ ./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 全称 “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 进程,进行调试命令。

使用多窗口查看源码与调试的读者,可以使用 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)
</layout_name>

可以通过 GDB cheat sheet[1],了解更多 GDB 使用方式。

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

在某种情况下发现 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)
</innodb_version_str></update_func_str(thd*,></check_func_str(thd*,>

假设需获取某一个连接进入 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

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

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

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

--debug [ = debug_options ]

[ = debug _ options ] 可识别字符 dtio 等。

若需获取代码中 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 的几种常见方法。当然,仅仅起到抛砖引玉的作用,更多好玩的技巧,还需读者自行深度挖掘。

Original: https://www.cnblogs.com/radondb/p/15702898.html
Author: RadonDB
Title: 工具 | 常用 MySQL 内核 Debug 技巧

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/507950/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • phpstrom以及webstrom等jetbrains全家桶激活方法

    因为最近重新安装了phpstrom,所以在网上找了许多激活方式,各种激活码和加公众号都试过了,没有一个能用的,直到我找到了以下的方式,亲测可用: 原理是我们通过代码搜索其他授权服务…

    数据库 2023年6月14日
    0152
  • MySQL事务、隔离级别

    一、事务简介 事务是操作的集合,它是一个不可分割的工作单元。事务将向整个系统提交或取消操作请求,即这些操作要么同时成功,要么同时失败。 [En] A transaction is …

    数据库 2023年5月24日
    079
  • 【黄啊码】使用think-queue产生大量日志文件怎么办?

    有时候某些原因程序出错,会有大量日志生成,最好调整下日志,单独出来。在配置文件config/queue.php开头添加: use think\facade\Log;Log::ini…

    数据库 2023年6月16日
    089
  • 容器化|在 S3 备份恢复 RadonDB MySQL 集群数据

    作者:程润科、钱芬视频:钱芬 上一篇文章我们演示了如何快速实现 MySQL 高可用集群部署,以及部署集群的校验和卸载方式。本文将演示如何对集群进行备份和恢复。 部署版本为 Rado…

    数据库 2023年5月24日
    091
  • CentOS服务器的网络配置与部署

    1.系统安装与软件安装 1.1选择CentOs7.9release版本用作所研发系统部署服务器,官网以及所选择镜像为地址为:http://ftp.sjtu.edu.cn/cento…

    数据库 2023年6月6日
    087
  • 一文读懂Spring框架中Bean的生命周期

    我们先来聊聊bean的生命周期: bean的生命周期图: AbstractAutowireCapableBeanFactory的docreateBean()方法(简单描述): 1….

    数据库 2023年6月6日
    0106
  • MySQL实战45讲之基础篇

    前言 本文主要记录学习 MySQL&#x5B9E;&#x6218;45&#x8BB2;&#x4E4B;&#x57FA;&#x7840…

    数据库 2023年5月24日
    0106
  • Python–生成器

    学习生成器之前,首先需要认识列表生成式,直奔主题。 1、简单列表生成式示例: 看样子好像很NB的样子,其实它等价于: 其实还是有点NB的,毕竟代码少了,手动嘻嘻嘻! 2、削微高级点…

    数据库 2023年6月9日
    0131
  • 一个Tomcat 如何部署多个项目?附多种解决方案及详细步骤!

    ; 此文源自一次多年前面试的面试题,民工哥将它总结出来分享给大家,希望对大家有所帮助,或者今后的面试中说不定会用的上。 首先,我们了解一下常见的Java Web服务器。 Tomca…

    数据库 2023年6月9日
    0167
  • BufferedImage类

    BufferedImage类(BufferedImage,是一个带缓冲区图像类,主要作用是将一副图片加载到内存中) BufferedImage类 是lmage的一个子类,Buffe…

    数据库 2023年6月11日
    0116
  • Mysql索引底层数据结构与算法

    一.索引概述是什么:索引是帮助MySQL高效获取数据的排好序的数据结构,索引叫”键”,优化好一个索引,可以提高数倍的性能, 类似于字典的音序表为什么要键索引…

    数据库 2023年6月11日
    0111
  • 重写Feign编码器

    有个spring cloud 架构的项目需要调用php小组的api接口,但php提供的接口入参大部分是下划线命名,而Java这边的实体类是按照驼峰编写,如果使用Fegin调用会导致…

    数据库 2023年6月6日
    082
  • String字符串用逗号拼接,防止最后一位是逗号

    StringBuilder sb = new StringBuilder(); for(String s strArr) { if (sb.length() > 0) {//…

    数据库 2023年6月16日
    0100
  • 数据库操作

    数据库操作 数据库基础数据库是一种 存储结构, 允许使用各种格式 输入、处理、检索 数据,且不用在每次需要数据时 重新输入数据。 select 语句: select语句 用于查询数…

    数据库 2023年6月16日
    0102
  • Python 学习笔记(七)–socket

    1.网络七层模型及主要协议 2.TCP的”三次握手”和四次挥手 三次握手 Step1:首先客户端向服务器端发送一段TCP报文; Step 2:服务器端接收到…

    数据库 2023年6月16日
    0114
  • Docker从入门到精通

    1 容器简介1.1 什么是 Linux 容器1.2 容器不就是虚拟化吗1.3 容器发展简史2 什么是 Docker?2.1 Docker 如何工作?2.2 Docker 技术是否与…

    数据库 2023年6月14日
    091
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球