从零开始学习MySQL调试跟踪(1)

  • GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。
  • GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。
  • 作者: Yejinrong/叶金荣
  • 文章来源:GreatSQL社区投稿

    1. 编译GreatSQL
    1. 安装gdb
    1. 开始调试GreatSQL源码
    • 3.1 利用gdb设置断点
    • 3.2 使用 Trace 文件调试

有时为了跟踪故障需要调试MySQL/GreatSQL源码,本文介绍如何在Linux下构建MySQL/GreatSQL源码调试环境。

在这之前,我也是一名小白,一起从零开始探索吧。

本文以CentOS 8.x环境下的GreatSQL 8.0.25-16版本为例。

1. 编译GreatSQL

查看系统环境:

$ cat /etc/system-release

CentOS Linux release 8.4.2105

首先,从https://gitee.com/GreatSQL/GreatSQL/releases/ 下载GreatSQL 8.0.25-16的源码包

  1. Source Code
Packages Size
greatsql-8.0.25-16.tar.gz 503M

接下来,参考文章 在Linux下源码编译安装GreatSQL 构建好编译环境。然后开始编译GreatSQL源码,编译参数中增加/修改debug相关选项,这样编译后得到的二进制文件才能支持调试模式,例如:

$ cd /opt/greatsql-8.0.25-16
$ mkdir -p build
$ cd build
$ cmake3 .. \
-DBOOST_INCLUDE_DIR=/opt/boost_73_0 \
-DLOCAL_BOOST_DIR=/opt/boost_73_0 \
-DCMAKE_INSTALL_PREFIX=/usr/local/GreatSQL-8.0.25-16-Linux-glibc2.28-x86_64 \
-DWITH_ZLIB=bundled \
-DWITH_NUMA=ON \
-DCMAKE_EXE_LINKER_FLAGS="-ljemalloc" \
-DBUILD_CONFIG=mysql_release \
-DWITH_TOKUDB=OFF \
-DWITH_ROCKSDB=OFF \
-DMAJOR_VERSION=8 \
-DMINOR_VERSION=0 \
-DPATCH_VERSION=25 \
-DWITH_UNIT_TESTS=OFF \
-DWITH_NDBCLUSTER=OFF \
-DWITH_SSL=system \
-DWITH_SYSTEMD=ON \
-DWITH_LDAP=OFF \
-DWITH_AUTHENTICATION_LDAP=OFF \
-DWITH_DEBUG=1 \
-DCMAKE_BUILD_TYPE=Debug \
&& make -j8 VERBOSE=1 && make install

主要是增加两个参数 -DWITH_DEBUG=1-DCMAKE_BUILD_TYPE=Debug,注意不要有参数 -DCMAKE_BUILD_TYPE=RelWithDebInfo

编译完成后,即可得到包含debug功能的GreatSQL二进制文件,执行下面的命令检查:

$ cd /usr/local/GreatSQL-8.0.25-16-Linux-glibc2.28-x86_64
$ ./bin/mysqld-debug --verbose --version

/usr/local/GreatSQL-8.0.25-16-Linux-glibc2.28-x86_64/bin/mysqld-debug  Ver 8.0.25-16-debug for Linux on x86_64 (Source distribution)

可以看到,输出的结果中包含 debug 关键字,这就表示成功了。

2. 安装gdb

直接执行yum安装gdb即可:

$ yum install -y gdb
$ gdb --version
GNU gdb (GDB) Red Hat Enterprise Linux 9.2-4.el8
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

gdb常用的调试相关指令有以下几个:

命令 缩写 备注
attach 挂接/进入准备调试的进程pid
detach 取消挂接进程(退出进程)
list l 显示多行源代码
break b 设置断点,程序运行到断点的位置会停下来
info i 描述程序的状态
run r 开始运行程序
display disp 跟踪查看某个变量,每次停下来都显示它的值
step s 执行下一条语句,如果该语句为函数调用,则进入函数执行其中的第一条语句
next n 执行下一条语句,如果该语句为函数调用,不会进入函数内部执行(即不会一步步地调试函数内部语句)
print p 打印内部变量值
continue c 继续程序的运行,直到遇到下一个断点
set var name=v 设置变量的值
start st 开始执行程序,在main函数的第一条语句前面停下来
file 装入需要调试的程序
kill k 终止正在调试的程序
watch 监视变量值的变化
backtrace bt 查看函数调用信息(堆栈)
frame f 查看栈帧
quit q 退出gdb

3. 开始调试GreatSQL源码

第一次运行gdb准备调试时,可能会提示类似下面的信息

warning: Unable to find libthread_db matching inferior's thread library, thread debugging will not be available.
0x00007ffb358ada41 in poll () from /lib64/libc.so.6
Missing separate debuginfos, use: dnf debuginfo-install keyutils-libs-1.5.10-9.el8.x86_64 ...

这表示缺少一些相关的debuginfo包,可以根据提示内容补充安装,例如:

dnf debuginfo-install keyutils-libs-1.5.10-9.el8.x86_64 ...

如果提示找不到这些安装包:

Could not find debuginfo package for the following installed packages: keyutils-libs-1.5.10-9.el8.x86_64 ...

可以检查yum配置文件 /etc/yum.repos.d/CentOS-Linux-Debuginfo.repo,确认是否设置了 enable = 1,例如:

# CentOS-Linux-Debuginfo.repo
#
# All debug packages are merged into a single repo, split by basearch, and are
# not signed.

[debuginfo]
name=CentOS Linux $releasever - Debuginfo
baseurl=http://debuginfo.centos.org/$releasever/$basearch/
gpgcheck=1
enabled=1    #<---这里要设置1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial

此外,还要把GreatSQL 8.0.25-16的源码包解压缩到 /opt 目录下:

$ tar zxf PATH/greatsql-8.0.25-16.tar.gz -C /opt/

接下来,演示如何跟踪调试。

先初始化GreatSQL数据文件,然后再启动GreatSQL服务进程:

# 初始化GreatSQL
$ cd /usr/local/GreatSQL-8.0.25-16-Linux-glibc2.28-x86_64
$ ./bin/mysqld-debug --no-defaults --initialize-insecure --user=mysql --datadir=./data

# 启动GreatSQL
$ ./bin/mysqld-debug --no-defaults --user=mysql --datadir=./data1 &

# 查看进程pid
$ ps -ef | grep mysqld
...
mysql    2644322 2542442  3 14:38 pts/7    00:00:01 ./bin/mysqld-debug --no-defaults --user=mysql --datadir=./data1

# 在另一个终端(终端#2),连入GreatSQL
$ mysql -S/tmp/mysql.sock
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 8.0.25-16-debug Source distribution
...
mysql>\s
...
Server version:         8.0.25-16-debug Source distribution
...

启动gdb,准备调试跟踪GreatSQL,我们分别演示几种不同方式。

3.1 利用gdb设置断点

终端#1 中启动gdb,并挂接GreatSQL进程,准备跟踪

$ gdb -p 2644322
GNU gdb (GDB) Red Hat Enterprise Linux 9.2-4.el8
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
...
Attaching to process 2644322
[New LWP 2643482]
[New LWP 2643483]
[New LWP 2643484]
...
[New LWP 2643522]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
--Type <RET> for more, q to quit, c to continue without paging--  #<-- 这里按下回车,即可进入
0x00007fb7ae93ba41 in __GI___poll (fds=0x7fb7ae229140, nfds=2, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:29
29        return SYSCALL_CANCEL (poll, fds, nfds, timeout);
(gdb)
(gdb) p mysql_sysvar_version  #<-- 打印变量,查看GreatSQL版本号
$1 = {flags = 68101, name = 0x7f10d1c6cc90 "innodb_version", comment = 0x6c47f92 "InnoDB version", check = 0x37dd9e2
     <check_func_str(THD*, SYS_VAR*, void*, st_mysql_value*)>, update = 0x37ddeb0 <update_func_str(THD*, SYS_VAR*, void*, void const*)>,
  value = 0x7e7c768 <innodb_version_str>, def_val = 0x6c38440 "8.0.25-15"}
(gdb) 
(gdb) 
(gdb) b mysql_execute_command  #<--- 输入指令"b dispatch_command"设置断点,意为当GreatSQL程序运行到这个函数时,就会停下来
Breakpoint 3 at 0x379c3f2: file /opt/greatsql-8.0.25-16/sql/sql_parse.cc, line 2875.
(gdb)

切换到 终端#2,随便执行一条SQL命令:

mysql> select 'debug' from dual;

回到 终端#1,继续调试:

(gdb) 
(gdb) bt  #<-- 打印函数调用信息
#0  dispatch_command (thd=0x7f10a3a0b000, com_data=0x7f10d12a7370, command=COM_QUERY) at /opt/greatsql-8.0.25-16/sql/sql_parse.cc:1605
#1  0x0000000003797c48 in do_command (thd=0x7f10a3a0b000) at /opt/greatsql-8.0.25-16/sql/sql_parse.cc:1388
#2  0x0000000003991168 in handle_connection (arg=0x7f10d1f9d120) at /opt/greatsql-8.0.25-16/sql/conn_handler/connection_handler_per_thread.cc:307
#3  0x00000000052e4b22 in pfs_spawn_thread (arg=0x7f10e8a45660) at /opt/greatsql-8.0.25-16/storage/perfschema/pfs.cc:2899
#4  0x00007f10eb1e917a in start_thread (arg=<optimized out>) at pthread_create.c:479
#5  0x00007f10e9128dc3 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
(gdb)
(gdb) p thd->m_query_string  #<-- 打印SQL语句
$14 = {str = 0x7f10a3a0e828 "select 'debug' from dual", length = 24}
(gdb)
(gdb) c  #<-- 继续执行,终端#2里被阻塞的SQL语句就可以执行了
Continuing.

切回 终端#2 查看SQL语句执行结果:

mysql> select 'debug' from dual;
+-------+
| debug |
+-------+
| debug |
+-------+
1 row in set (12 min 11.55 sec)

可以看到,因为一直被阻塞,这条SQL请求耗时超过12分钟。当 终端#2 的连接断开退出后,可以看到gdb端也有相应提示:

Thread 39 "mysqld-debug" hit Breakpoint 1, dispatch_command (thd=0x7f10a3a0b000, com_data=0x7f10d12a7370, command=COM_QUIT)
    at /opt/greatsql-8.0.25-16/sql/sql_parse.cc:1605
1605      bool error = false;
(gdb)

如果不想继续跟踪调试了,只需输入指令 qquit 即可退出gdb。

(gdb) quit
A debugging session is active.

        Inferior 1 [process 2644322] will be detached.

Quit anyway? (y or n) y
Detaching from program: /usr/local/GreatSQL-8.0.25-16-Linux-glibc2.28-x86_64/bin/mysqld-debug, process 2644322
[Inferior 1 (process 2644322) detached]

3.2 使用 Trace 文件调试

还可以在GreatSQL客户端中设置变量 debug 为不同值,就可以输出GreatSQL运行过程中涉及的调用模块、函数、状态信息等全部信息,并记录到本地文件中。用法示例:

mysql> SET SESSION debug = 'debug_options';

变量 debug 支持多种设置模式:

debug_options = field_1:field_2:...:field_N
field = [+|-]flag[,modifier,modifier,...,modifier]

+, - 表示从当前debug值添加或者减少某些选项。

flag相关可选项如下:

flag 说明
d 开启DBUG
f 只跟踪指定的函数
F 跟踪指定的源码文件
i 跟踪指定的线程
L 跟踪指定的源码行数
n 打印函数调用层次序号
N 输出日志从0开始打印行号
o 指定输出到某个文件
O 类似o,每次写文件都会flush,reopen
P 匹配DBUG_PROCESS
p 打印process name
t 打印函数调用和退出

使用案例1(精简模式)

# 设置debug选项
mysql> set session debug='d:t:o,/tmp/mysqld.trace';

# 执行SQL请求
mysql> select 'debug' from dual;
+-------+
| debug |
+-------+
| debug |
+-------+
1 row in set (0.00 sec)

查看生成的trace文件:

$ cat /tmp/mysqld.trace
...
>do_command
| >THD::clear_error
| <THD::clear_error
| >Diagnostics_area::reset_diagnostics_area
| <Diagnostics_area::reset_diagnostics_area
| >my_net_set_read_timeout
| | enter: timeout: 28800
| | >vio_socket_timeout
| | <vio_socket_timeout
| <my_net_set_read_timeout
| >vio_is_blocking
| <vio_is_blocking
| >net_read_raw_loop
| | >vio_read
| | | >vio_is_blocking
| | | <vio_is_blocking
| | | >vio_io_wait
| | | <vio_io_wait
| | <vio_read
| <net_read_raw_loop
| THD::enter_stage: 'starting' /opt/greatsql-8.0.25-16/sql/conn_handler/init_net_server_extension.cc:102
...

使用案例2(复杂模式)增加了打印文件名和行号等信息,更方便定位查找。

mysql> set session debug='d:t:L:F:o,/tmp/mysqld.trace';
mysql> select 'debug' from dual;
...

查看生成的trace文件:

$ cat /tmp/mysqld.trace
...
  sql_parse.cc: <do_command
  sql_parse.cc:  1269: >do_command
   sql_class.h:  3287: | >THD::clear_error
   sql_class.h: | <THD::clear_error
  sql_error.cc:   357: | >Diagnostics_area::reset_diagnostics_area
  sql_error.cc: | <Diagnostics_area::reset_diagnostics_area
   net_serv.cc:  2246: | >my_net_set_read_timeout
   net_serv.cc:  2247: | | enter: timeout: 28800
  viosocket.cc:   380: | | >vio_socket_timeout
  viosocket.cc: | | <vio_socket_timeout
   net_serv.cc: | <my_net_set_read_timeout
  viosocket.cc:   373: | >vio_is_blocking
  viosocket.cc: | <vio_is_blocking
   net_serv.cc:  1341: | >net_read_raw_loop
  viosocket.cc:   169: | | >vio_read
  viosocket.cc:   373: | | | >vio_is_blocking
  viosocket.cc: | | | <vio_is_blocking
  viosocket.cc:  1118: | | | >vio_io_wait
  viosocket.cc: | | | <vio_io_wait
  viosocket.cc: | | <vio_read
   net_serv.cc: | <net_read_raw_loop
  sql_parse.cc:   320: | THD::enter_stage: 'starting' /opt/greatsql-8.0.25-16/sql/conn_handler/init_net_server_extension.cc:102
...

本文简单演示了如何跟踪调试GreatSQL的几种方法,更多有趣实用的方法还有待进一步挖掘,一起探索新世界吧。

P.S,我也在MacOS环境下构建了基于vscode的跟踪调试环境,但还是更喜欢在Linux终端命令行模式下工作,所以本文没介绍如何利用vscode跟踪调试,有兴趣的读者可以根据其他资料自行构建。


Enjoy GreatSQL ?

关于 GreatSQL

GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。

相关链接: GreatSQL社区 Gitee GitHub Bilibili

GreatSQL社区:

社区博客有奖征稿详情:https://greatsql.cn/thread-100-1-1.html

image-20230105161905827

技术交流群:

微信:扫码添加GreatSQL社区助手微信好友,发送验证信息加群

image-20221030163217640

原文链接:https://www.cnblogs.com/greatsql/p/17306368.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:从零开始学习MySQL调试跟踪(1) - Python技术站

(0)
上一篇 2023年4月17日
下一篇 2023年4月17日

相关文章

  • mysql关联子查询的一种优化方法分析

    标题 MySQL关联子查询的一种优化方法分析 文本 在MySQL中,查询语句的执行效率是非常重要的。使用子查询进行关联查询时,如果处理不当,则很快就会遇到效率问题。本文将讨论MySQL关联子查询的一种优化方法。该方法可以提高查询效率,避免耗时的子查询。 优化方法 我们可以通过将子查询转换成JOIN查询来实现关联查询的优化。这种优化方法可以避免执行延迟高的子查…

    MySQL 2023年5月19日
    00
  • mysql中的多行查询结果合并成一个

    原文:http://blog.csdn.net/lifuxiangcaohui/article/details/6132147   SELECT GROUP_CONCAT(md.data1) FROM DATA md,contacts cc WHERE md.conskey=cc.id AND md.mimetype_id= 5 AND md.user_id…

    MySQL 2023年4月13日
    00
  • MySQL:reading initial communication packet问题解决方法

    MySQL:reading initial communication packet问题一般是由于MySQL服务端没有正确监听本地IP地址和端口所导致的。解决方法主要是检查MySQL配置文件和网络连接。 下面是具体的解决方法: 1. 检查MySQL配置文件 进入MySQL的配置文件 my.cnf(一般位于 /etc/mysql/ 或 /usr/local/m…

    MySQL 2023年5月18日
    00
  • mysql 占用大量写I/O

    zabbix告警,发现某台存放监控数据的数据库主机CPU的IOwait较高,一直持续较长时间。 登录服务器查看磁盘IO发现队列高达90%多,而且经常反复如此 通过iotop查看发现占用io较大的进程是mysql 登录mysql查看show processlist,发现基本上每次io队列较高时都是在insert时,以为是插入语句有问题,于是打开mysql慢查询…

    MySQL 2023年4月13日
    00
  • mysql-5.5.28源码安装过程中错误总结

    下面是“mysql-5.5.28源码安装过程中错误总结”的完整攻略。 1. 下载和解压源码包 首先需要从官方网站下载mysql-5.5.28的源码包,并将其解压到指定的目录下: wget http://cdn.mysql.com//Downloads/MySQL-5.5/mysql-5.5.28.tar.gz tar zxvf mysql-5.5.28.ta…

    MySQL 2023年5月18日
    00
  • 很全面的Mysql数据库、数据库表、数据基础操作笔记(含代码)

    很全面的Mysql数据库、数据库表、数据基础操作笔记(含代码) 什么是MySQL数据库 MySQL是一种开源的关系型数据库管理系统,被广泛的应用在Web应 用程序中,是流行的数据库之一。 如何安装和使用MySQL 安装MySQL 我们可以在MySQL官网下载并安装MySQL,也可以使用apt-get(Ubuntu)或yum(CentOS)来安装MySQL。 …

    MySQL 2023年5月18日
    00
  • mysql制作外键出现duplicate key name错误问题及解决

    当在 MySQL 数据库中创建外键时,可能会遇到“Duplicate key name”的错误。这个错误信息通常表示引入的外键名与数据库中已有的索引名重复,因此需要更改外键名或者删除重复的索引。 以下是解决这个问题的完整攻略: 1. 确认错误信息 当创建外键时出现“Duplicate key name”的错误信息时,需要确认是否为外键名称重复导致的问题。在 …

    MySQL 2023年5月18日
    00
  • MySQL5.7中的sql_mode默认值带来的坑及解决方法

    MySQL5.7中的sql_mode默认值带来的坑及解决方法 在MySQL5.7版本中,sql_mode的默认值发生了变化,从之前的空值改成了ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE…

    MySQL 2023年5月18日
    00
合作推广
合作推广
分享本页
返回顶部