(转)GDB调试MySQL
原文:https://developer.aliyun.com/article/178794
https://blog.csdn.net/weixin_41561946/article/details/107584782
https://riverdba.github.io/2017/05/04/gdb-debug-mysql/
GDB主要帮助我们完成下面四个方面的功能:
1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
3、当程序被停住时,可以检查此时你的程序中所发生的事。
4、你可以改变你的程序,将一个BUG产生的影响修正从而测试其他BUG。
在学习Oracle的时候使用GDB调试,主要是关于学习Oracle的闩锁原理,那么,为什么要用GDB调试MySQL:
1.识别故障
2.场景重现
3.创建测试案例确认BUG
4.定位缺陷根源
5.测试和创建补丁修复BUG
下面开始学习GDB调试MySQL
1、安装编译MySQL需要的软件包
yum install -y cmake make gcc gcc-c++ ncurses-devel bison gdb
2、编译MySQL
# git clone https://github.com/mysql/mysql-server.git
# cd mysql-server
# git checkout mysql-5.7.19
# cd BUILD; cmake .. -DDOWNLOAD_BOOST=1 -DWITH_DEBUG=1 -DWITH_UNIT_TESTS=off
# make
# make install
3、连接MySQL程序
3.1、查看MySQL进程ID
[root@debug ~]# ps -ef | grep mysql
root 24589 1 0 07:58 ? 00:00:00 /bin/sh /usr/local/mysql/bin/mysqld_safe --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data --user=mysql
mysql 24794 24589 0 07:58 ? 00:00:01 /usr/local/mysql/bin/mysqld --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data --plugin-dir=/usr/local/mysql/lib/plugin --user=mysql --log-error=/usr/local/mysql/data/mysql-debug.log --pid-file=debug.pid --socket=/tmp/mysql.sock --port=3306
root 25009 24993 0 11:29 pts/2 00:00:00 grep mysql
|
3.2、GDB使用attach连接MySQL进程ID
[root@debug ~]# gdb
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-92.el6)
Copyright (C) 2010 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. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) attach 24794
Attaching to process 24794
Reading symbols from /usr/local/mysql/bin/mysqld...done.
Reading symbols from /lib64/libpthread.so.0...(no debugging symbols found)...done.
[New LWP 24969]
[New LWP 24824]
[New LWP 24821]
[New LWP 24820]
[New LWP 24819]
[New LWP 24818]
[New LWP 24817]
[New LWP 24816]
[New LWP 24815]
[New LWP 24814]
[New LWP 24813]
[New LWP 24812]
[New LWP 24811]
[New LWP 24810]
[New LWP 24809]
[New LWP 24808]
[New LWP 24806]
[New LWP 24805]
[New LWP 24804]
[New LWP 24803]
[New LWP 24802]
[New LWP 24801]
[New LWP 24800]
[New LWP 24799]
[New LWP 24798]
[New LWP 24797]
[New LWP 24796]
[New LWP 24795]
[Thread debugging using libthread_db enabled]
Loaded symbols for /lib64/libpthread.so.0
Reading symbols from /lib64/libcrypt.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib64/libcrypt.so.1
Reading symbols from /lib64/libdl.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/libdl.so.2
Reading symbols from /lib64/librt.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib64/librt.so.1
Reading symbols from /usr/lib64/libstdc++.so.6...(no debugging symbols found)...done.
Loaded symbols for /usr/lib64/libstdc++.so.6
Reading symbols from /lib64/libm.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libm.so.6
Reading symbols from /lib64/libgcc_s.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib64/libgcc_s.so.1
Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Reading symbols from /lib64/libfreebl3.so...(no debugging symbols found)...done.
Loaded symbols for /lib64/libfreebl3.so
Reading symbols from /lib64/libnss_files.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/libnss_files.so.2
0x00007f8801dfd383 in poll () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.209.el6_9.2.x86_64 libgcc-4.4.7-18.el6.x86_64 libstdc++-4.4.7-18.el6.x86_64 nss-softokn-freebl-3.14.3-23.el6_7.x86_64
|
4、设置断点
4.1、查看插入语句的源码sql_insert.cc的423行的函数Sql_cmd_insert::mysql_insert
bool Sql_cmd_insert::mysql_insert(THD *thd,TABLE_LIST *table_list)
{
DBUG_ENTER("mysql_insert");
LEX *const lex= thd->lex;
int error, res;
bool err= true;
bool transactional_table, joins_freed= FALSE;
bool changed;
bool is_locked= false;
ulong counter= 0;
ulonglong id;
|
4.2、在session1中的gdb设置insert的断点
(gdb) b Sql_cmd_insert::mysql_insert
Breakpoint 1 at 0x17bd1b9: file /root/mysql-server/sql/sql_insert.cc, line 423.
|
4.3、查看断点信息,从下往上看,使用到了多个MySQL函数。
(gdb) bt
#0 0x00007f8801dfd383 in poll () from /lib64/libc.so.6
#1 0x00000000016c1155 in Mysqld_socket_listener::listen_for_connection_event (this=0x45d8870)
at /root/mysql-server/sql/conn_handler/socket_connection.cc:852
#2 0x0000000000ece89c in Connection_acceptor<Mysqld_socket_listener>::connection_event_loop (this=0x45b5ec0)
at /root/mysql-server/sql/conn_handler/connection_acceptor.h:66
#3 0x0000000000ec6226 in mysqld_main (argc=17, argv=0x3ab4248) at /root/mysql-server/sql/mysqld.cc:5045
#4 0x0000000000ebd2d4 in main (argc=9, argv=0x7fffb2aa7408) at /root/mysql-server/sql/main.cc:25
|
4.4、在设置了断点之后,在另一个session2中登录数据库,发现无法登录,hung住了,在gdb中执行next(执行下一步代码),可以看到在socket_connection.cc源码第859行无法继续,代码大致是说要获取系统的socket,还有一些监听信息,由于太多了,直接在gdb中执行continue(到下一个可执行的代码),此时session2已经登录成功。
(gdb) n
Single stepping until exit from function poll,
which has no line number information.
Mysqld_socket_listener::listen_for_connection_event (this=0x45d8870) at /root/mysql-server/sql/conn_handler/socket_connection.cc:859
859 if (retval < 0 && socket_errno != SOCKET_EINTR)
(gdb) n
871 if (retval < 0 || abort_loop)
(gdb) n
876 MYSQL_SOCKET listen_sock= MYSQL_INVALID_SOCKET;
(gdb) n
877 bool is_unix_socket= false;
(gdb) n
879 for (uint i= 0; i < m_socket_map.size(); ++i)
(gdb) n
881 if (m_poll_info.m_fds[i].revents & POLLIN)
(gdb) n
879 for (uint i= 0; i < m_socket_map.size(); ++i)
(gdb) n
881 if (m_poll_info.m_fds[i].revents & POLLIN)
(gdb) n
883 listen_sock= m_poll_info.m_pfs_fds[i];
(gdb) n
884 is_unix_socket= m_socket_map[listen_sock];
(gdb) n
885 break;
(gdb) n
904 for (uint retry= 0; retry < MAX_ACCEPT_RETRY; retry++)
(gdb) n
906 socket_len_t length= sizeof(struct sockaddr_storage);
(gdb) n
908 (struct sockaddr *)(&cAddr), &length);
(gdb) n
909 if (mysql_socket_getfd(connect_sock) != INVALID_SOCKET ||
(gdb) n
… ...
(gdb) c
Continuing.
|
4.5、session2此时的select操作都是一切正常的
[root@localhost:(none)][11:41:15am] MySQL-> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
[root@localhost:test][11:49:12am] MySQL-> show tables;
+----------------+
| Tables_in_test |
+----------------+
| t |
| t1 |
+----------------+
2 rows in set (0.00 sec)
[root@localhost:test][11:49:16am] MySQL-> select * from t;
+------+------+
| id | name |
+------+------+
| 1 | aaa |
| 2 | aaa |
| 3 | aaa |
| 4 | aaa |
+------+------+
4 rows in set (0.00 sec)
|
4.6、session2做insert操作的时候,又一次hung住了,session1打印出了断点的信息,在mysql_insert:423行,直到执行continue,session2才能正常插入数据。
(gdb) c
Continuing.
[Switching to Thread 0x7f87e00b4700 (LWP 24824)]
Breakpoint 1, Sql_cmd_insert::mysql_insert (this=0x7f87f40147b8, thd=0x7f87f401bc60, table_list=0x7f87f4013fe0)
at /root/mysql-server/sql/sql_insert.cc:423
423 DBUG_ENTER("mysql_insert");
(gdb) n
425 LEX *const lex= thd->lex;
(gdb) n
427 bool err= true;
(gdb) c
Continuing.
|
gdb使用小技巧
当数据库连接满了时,可以通过下面命令调整连接数
gdb --pid=`pidof mysqld` -ex "set max_connections=1500" --batch
1
总结与思考
1、gdb的小技巧能够使用在postgresql和oracle中吗
2、gdb调试mysqld时会阻塞整个数据库
3、gdb也可以调试某个数据库连接进程,并不会影响其他新连接
参考资料
https://blog.csdn.net/weixin_34049032/article/details/88589069
https://blog.csdn.net/n88Lpo/article/details/106484780
技术链接
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
2020-06-04 (转)Linux系统:centos7下搭建Rocketmq4.3中间件,配置监控台
2019-06-04 (转)SQLAlchemy入门和进阶