利用GDB调试 MSQL(1)

简介: 利用GDB调试 MSQL

啃完O'reilly的《高性能mysql》、姜老师的《MySQL技术内幕》,再加上个2,3年的实战经验,就基本可以成为一名能独立处理问题的DBA了。但有些时候遇到些很刁钻的疑难杂症的话,那就束手无策了。所以要想技术水平更进一步的话,源码调试是避不开的。

GDB 简介

GDB 是 Linux 系统中,非常常见的调试工具,它有以下功能:

  • Start your program, specifying anything that might affect its behavior.
  • Make your program stop on specified conditions.
  • Examine what has happened, when your program has stopped.
  • Change things in your program, so you can experiment with correcting the effects of one bug and go on to learn about another.

常用的参数命令:

  • info threads:查看全部线程
  • thread n:指定某个线程
  • b:在某处打断点
  • c:继续往下走
  • s:执行一行代码,如果代码函数调用,则进入函数
  • n:执行一行代码,函数调用不进入
  • p:打印某个变量值
  • list:打印代码的文本信息
  • bt:查看某个线程的栈帧
  • info b:查看当前所有断点信息

调试环境搭建

直接在 linux 下面使用 gdb,这种应该是目前市面上最简单有效的方式。

1. 安装gdb
yum install -y cmake make gcc gcc-c++ ncurses-devel bison gdb
2. 下载、解压源码
wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-boost-5.7.25.tar.gz

tar zxvf mysql-boost-5.7.25.tar.gz
mkdir -p /gdb/mysql/
mkdir -p /gdb/data/
3. 安装数据库
cmake -DCMAKE_INSTALL_PREFIX=/gdb/mysql/ -DMYSQL_DATADIR=/gdb/data/ -DSYSCONFDIR=/gdb/mysql/ -DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_ARCHIVE_STORAGE_ENGINE=1 -DWITH_BLACKHOLE_STORAGE_ENGINE=1 -DWITH_FEDERATED_STORAGE_ENGINE=1 -DWITH_PARTITION_STORAGE_ENGINE=1 -DMYSQL_UNIX_ADDR=/gdb/mysql/mysql3.sock -DMYSQL_TCP_PORT=3306 -DENABLED_LOCAL_INFILE=1 -DEXTRA_CHARSETS=all -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DMYSQL_USER=mysql -DWITH_BINLOG_PREALLOC=ON -DWITH_BOOST=/gdb/mysql-5.7.25/boost/boost_1_59_0 -DWITH_DEBUG=1

-DWITH_DEBUG=1 是最关键的,它的作用是开启DBUG

make&&make install
4. 初始化数据库
vim /etc/my.cnf
#简易配置下my.cnf文件
[client]
port = 3306
socket = /gdb/data/mysqld.sock
[mysqld]
port = 3306
socket =/gdb/data/mysqld.sock
skip-external-locking
key_buffer_size = 8M
max_allowed_packet = 1M
table_open_cache = 64
sort_buffer_size = 512K
net_buffer_length = 8K
read_buffer_size = 128K
read_rnd_buffer_size = 256K
myisam_sort_buffer_size = 8M
lower_case_table_names=1
innodb_buffer_pool_size=300M
log-bin=mysql-bin
character_set_server=utf8
binlog_format=row
datadir=/gdb/data
log-error =/gdb/data/error.log
pid-file = /gdb/data/mysql.pid
innodb_log_file_size=512M
innodb_log_files_in_group = 3
sql_mode=''
autocommit=1
server-id = 1
max_connections=1500
wait_timeout=70
interactive_timeout=70
skip-name-resolve
[mysqldump]
quick
max_allowed_packet = 16M
[myisamchk]
key_buffer_size = 20M
sort_buffer_size = 20M
read_buffer = 2M
write_buffer = 2M
5. 启动数据库

赋权,以便mysql用户有权限在该目录下生成文件:

chown -R mysql:mysql /gdb/data

初始化数据库命令:

cd /gdb/mysql/bin
./mysqld --initialize --user=mysql --basedir=/gdb/mysql --datadir=/gdb/data

启动数据库:

cd /gdb/mysql/support-files
./mysql.server start

insert 断点调试

1. 查看 mysql 进程 id

[root@ops sql]# ps aux | grep mysql
root 629 0.0 0.0 112724 972 pts/2 S+ 14:52 0:00 grep -E --color=auto mysql
root 20926 0.0 0.0 113312 1628 pts/0 S 11:15 0:00 /bin/sh /gdb/mysql/bin/mysqld_safe --datadir=/gdb/data --pid-file=/gdb/data/mysql.pid
mysql 21357 0.0 5.8 1740820 223820 pts/0 Sl 11:15 0:01 /gdb/mysql/bin/mysqld --basedir=/gdb/mysql --datadir=/gdb/data --plugin-dir=/gdb/mysql/lib/plugin --user=mysql --log-error=/gdb/data/error.log --pid-file=/gdb/data/mysql.pid --socket=/gdb/data/mysqld.sock --port=3306

可以看到此时mysql的进程号为:20926

2. gdb 中 attach mysql 进程

[root@ops ~]# gdb
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-119.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html&gt;
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/&gt;.
(gdb) attach 21357
Attaching to process 21357
Reading symbols from /gdb/mysql/bin/mysqld...done.
Reading symbols from /lib64/libpthread.so.0...(no debugging symbols found)...done.
[New LWP 21617]
[New LWP 21387]
[New LWP 21386]
[New LWP 21384]
[New LWP 21383]
[New LWP 21382]
[New LWP 21381]
[New LWP 21380]
[New LWP 21379]
[New LWP 21378]
[New LWP 21377]
[New LWP 21376]
[New LWP 21375]
[New LWP 21374]
[New LWP 21373]
[New LWP 21369]
[New LWP 21368]
[New LWP 21367]
[New LWP 21366]
[New LWP 21365]
[New LWP 21364]
[New LWP 21363]
[New LWP 21362]
[New LWP 21361]
[New LWP 21360]
[New LWP 21359]
[New LWP 21358]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
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 /lib64/libstdc++.so.6...(no debugging symbols found)...done.
Loaded symbols for /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...Reading symbols from /lib64/libfreebl3.so...(no debugging symbols found)...done.
(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
Reading symbols from /lib64/libnss_sss.so.2...Reading symbols from /lib64/libnss_sss.so.2...(no debugging symbols found)...done.
(no debugging symbols found)...done.
Loaded symbols for /lib64/libnss_sss.so.2
0x00002b15ce803f0d in poll () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.17-222.el7.x86_64 libgcc-4.8.5-39.el7.x86_64 libstdc++-4.8.5-39.el7.x86_64 nss-softokn-freebl-3.34.0-2.el7.x86_64 sssd-client-1.16.0-19.el7.x86_64
(gdb)

3. 找到断点

这次看的是 insert 插入的流程,找到 sql_insert.cc 文件:

image.png

源码中的函数为:Sql_cmd_insert::mysql_insert

4. 设置断点

(gdb) b Sql_cmd_insert::mysql_insert
Breakpoint 1 at 0x175aed9: file /gdb/mysql-5.7.25/sql/sql_insert.cc, line 423.

然后查看下线程的栈帧:

(gdb) bt
#0 0x00002b15ce803f0d in poll () from /lib64/libc.so.6
#1 0x0000000001667f87 in Mysqld_socket_listener::listen_for_connection_event (this=0x3967430) at /gdb/mysql-5.7.25/sql/conn_handler/socket_connection.cc:852
#2 0x0000000000eb15cc in Connection_acceptor<Mysqld_socket_listener>::connection_event_loop (this=0x4f882e0) at /gdb/mysql-5.7.25/sql/conn_handler/connection_acceptor.h:66
#3 0x0000000000ea904a in mysqld_main (argc=38, argv=0x383c248) at /gdb/mysql-5.7.25/sql/mysqld.cc:5149
#4 0x0000000000ea01bd in main (argc=9, argv=0x7ffc73765b88) at /gdb/mysql-5.7.25/sql/main.cc:25

5. 数据库登陆

gdb断点设置完后,起个新的数据库连接:

image.png

会发现此时无法登陆,在gdb中执行next:

(gdb) n
Single stepping until exit from function poll,
which has no line number information.
Mysqld_socket_listener::listen_for_connection_event (this=0x3967430) at /gdb/mysql-5.7.25/sql/conn_handler/socket_connection.cc:859
859 if (retval < 0 && socket_errno != SOCKET_EINTR)

通过输出可以知道数据库处于获取系统 socket 状态。接下来需要跳过的步骤有些多,我们直接使用 continue (直接到下一段可执行代码)

(gdb) c
Continuing.

新起客户端连接成功:

[root@ops bin]# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 14
Server version: 5.7.25-debug-log Source distribution
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>


            </div>
相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
相关文章
|
XML 移动开发 API
微信支付开发(7) H5支付
关键字:微信支付 微信支付v3 H5支付 wap支付 prepay_id 作者:方倍工作室原文: http://www.cnblogs.com/txw1958/p/wxpayv3_h5.html    本文介绍微信支付下的H5支付实现流程。
3799 1
|
12月前
|
Java 数据库连接 Maven
最新版 | 深入剖析SpringBoot3源码——分析自动装配原理(面试常考)
自动装配是现在面试中常考的一道面试题。本文基于最新的 SpringBoot 3.3.3 版本的源码来分析自动装配的原理,并在文未说明了SpringBoot2和SpringBoot3的自动装配源码中区别,以及面试回答的拿分核心话术。
最新版 | 深入剖析SpringBoot3源码——分析自动装配原理(面试常考)
|
Go 微服务
Go语言微服务框架 - 3.日志库的选型与引入
衡量日志库有多个指标,我们今天重点关注两点:简单易用 与 高性能。简单易用是一个日志库能被广泛使用的必要条件,而高性能则是企业级的日志库非常重要的衡量点,也能在源码层面对我们有一定的启发。
929 1
|
安全 前端开发 Java
Spring Security的授权管理器实现
Spring Security的授权管理器涉及用户登录后的token验证和权限检查。当用户携带token访问时,框架会验证token合法性及用户访问权限。自定义授权管理器`TokenAuthorizationManager`需实现`AuthorizationManager&lt;RequestAuthorizationContext&gt;`接口,处理校验逻辑,包括解析token、判断用户角色与访问资源的匹配。配置中在`SecurityConfig`注册该管理器以生效。测试表明,具有不同角色的用户可访问相应权限的资源,否则返回403错误。
445 4
|
数据采集 分布式计算 数据挖掘
数据收集与整合
数据收集与整合
374 2
|
存储 分布式计算 Hadoop
Hadoop-33 HBase 初识简介 项目简介 整体架构 HMaster HRegionServer Region
Hadoop-33 HBase 初识简介 项目简介 整体架构 HMaster HRegionServer Region
204 2
|
tengine 网络安全
keepalived——tengine集群主备均有VIP
keepalived——tengine集群主备均有VIP
141 0
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的数字家庭网站的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的数字家庭网站的详细设计和实现(源码+lw+部署文档+讲解等)
105 2
|
前端开发
canvas详解07-裁剪
canvas详解07-裁剪
180 1
|
芯片 内存技术
Emerson / Motorola MVME6100 VME总线板卡
Emerson / Motorola MVME6100 VME总线板卡