利用GDB调试 MSQL(2)

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: 利用GDB调试 MSQL

6. 数据库插入

插入操作前,切换schema和查询都是没问题的:

mysql> use gdb
Database changed
mysql> show tables;
+---------------+
| Tables_in_gdb |
+---------------+
| test          |
+---------------+
1 row in set (0.00 sec)
mysql> select * from test;
+------+
| id   |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)

插入一条 id=3 的数据,出现了等待:

  1. mysql> insert into test values (3);

7. 分析断点信息

断点触发,如下:

(gdb) c

Continuing.
[Switching to Thread 0x2b15faf02700 (LWP 21617)]
Breakpoint 1, Sql_cmd_insert::mysql_insert (this=0x2b1614008348, thd=0x2b1614003af0, table_list=0x2b1614007db8) at /gdb/mysql-5.7.25/sql/sql_insert.cc:423
423 DBUG_ENTER("mysql_insert");

bt 命令展示栈帧:

(gdb) bt
#0 Sql_cmd_insert::mysql_insert (this=0x2b1614008348, thd=0x2b1614003af0, table_list=0x2b1614007db8) at /gdb/mysql-5.7.25/sql/sql_insert.cc:423
#1 0x000000000176256e in Sql_cmd_insert::execute (this=0x2b1614008348, thd=0x2b1614003af0) at /gdb/mysql-5.7.25/sql/sql_insert.cc:3118
#2 0x000000000153b093 in mysql_execute_command (thd=0x2b1614003af0, first_level=true) at /gdb/mysql-5.7.25/sql/sql_parse.cc:3596
#3 0x0000000001540820 in mysql_parse (thd=0x2b1614003af0, parser_state=0x2b15faf01690) at /gdb/mysql-5.7.25/sql/sql_parse.cc:5570
#4 0x0000000001536131 in dispatch_command (thd=0x2b1614003af0, com_data=0x2b15faf01df0, command=COM_QUERY) at /gdb/mysql-5.7.25/sql/sql_parse.cc:1484
#5 0x0000000001534f9a in do_command (thd=0x2b1614003af0) at /gdb/mysql-5.7.25/sql/sql_parse.cc:1025
#6 0x00000000016658dc in handle_connection (arg=0x39610f0) at /gdb/mysql-5.7.25/sql/conn_handler/connection_handler_per_thread.cc:306
#7 0x0000000001ced592 in pfs_spawn_thread (arg=0x5508e50) at /gdb/mysql-5.7.25/storage/perfschema/pfs.cc:2190
#8 0x00002b15cd699e25 in start_thread () from /lib64/libpthread.so.0
#9 0x00002b15ce80ebad in clone () from /lib64/libc.so.6

接下来输入 n 会逐行输出,我们这里直接 continue,阻塞的 insert 也完成了:

mysql> insert into test values (3);
Query OK, 1 row affected (2 min 49.57 sec)

发布一个特殊版本的mysql

有些函数所在源码的位置比较好理解,比如上面的 insert 功能,或者 delete 功能。是不是可以通过修改 delete 函数,打包一个数据永不会被删除的 mysql 呢?

定位函数位置

先追踪mysql进程:

(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 5584]
[New LWP 5583]
[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

delete函数这里打上断点:

(gdb) b Sql_cmd_delete::mysql_delete
Breakpoint 1 at 0x175198b: file /gdb/mysql-5.7.25/sql/sql_delete.cc, line 50.

数据库执行delete语句触发断点:

mysql> delete from test where id =3;

gbk断点信息:

Breakpoint 1, Sql_cmd_delete::mysql_delete (this=0x2b16040020c8, thd=0x2b1604007e30, limit=18446744073709551615) at /gdb/mysql-5.7.25/sql/sql_delete.cc:50
50 DBUG_ENTER("mysql_delete");

查看相关栈帧:

#0  Sql_cmd_delete::mysql_delete (this=0x2b16040020c8, thd=0x2b1604007e30, limit=18446744073709551615) at /gdb/mysql-5.7.25/sql/sql_delete.cc:50
#1 0x0000000001755cc6 in Sql_cmd_delete::execute (this=0x2b16040020c8, thd=0x2b1604007e30) at /gdb/mysql-5.7.25/sql/sql_delete.cc:1392
#2 0x000000000153b12f in mysql_execute_command (thd=0x2b1604007e30, first_level=true) at /gdb/mysql-5.7.25/sql/sql_parse.cc:3606
#3 0x0000000001540820 in mysql_parse (thd=0x2b1604007e30, parser_state=0x2b15faf43690) at /gdb/mysql-5.7.25/sql/sql_parse.cc:5570
#4 0x0000000001536131 in dispatch_command (thd=0x2b1604007e30, com_data=0x2b15faf43df0, command=COM_QUERY) at /gdb/mysql-5.7.25/sql/sql_parse.cc:1484
#5 0x0000000001534f9a in do_command (thd=0x2b1604007e30) at /gdb/mysql-5.7.25/sql/sql_parse.cc:1025
#6 0x00000000016658dc in handle_connection (arg=0x54b6510) at /gdb/mysql-5.7.25/sql/conn_handler/connection_handler_per_thread.cc:306
#7 0x0000000001ced592 in pfs_spawn_thread (arg=0x5508e50) at /gdb/mysql-5.7.25/storage/perfschema/pfs.cc:2190
#8 0x00002b15cd699e25 in start_thread () from /lib64/libpthread.so.0
#9 0x00002b15ce80ebad in clone () from /lib64/libc.so.6

修改源码

可以看到 #1 是 Sql_cmd_delete::execute ,这个就是 delete 处理的函数,去源代码中找到相应函数:

把正真实现删除逻辑的代码给注释掉,返回的 res 值直接赋成 true:

  1. bool Sql_cmd_delete::execute(THD thd)
  2. {
  3. DBUG_ASSERT(thd->lex->sql_command == SQLCOM_DELETE);

  4. LEX const lex= thd->lex;
  5. SELECT_LEX const select_lex= lex->select_lex;
  6. SELECT_LEX_UNIT const unit= lex->unit;
  7. TABLE_LIST const first_table= select_lex->get_table_list();
  8. TABLE_LIST const all_tables= first_table;

  9. if (delete_precheck(thd, all_tables))
  10. return true;
  11. DBUG_ASSERT(select_lex->offset_limit == 0);
  12. unit->set_limit(select_lex);

  13. / Push ignore / strict error handler /
  14. Ignore_error_handler ignore_handler;
  15. Strict_error_handler strict_handler;
  16. if (thd->lex->is_ignore())
  17. thd->push_internal_handler(&ignore_handler);
  18. else if (thd->is_strict_mode())
  19. thd->push_internal_handler(&strict_handler);

  20. /注释以下删除逻辑的代码/
  21. /
  22. MYSQL_DELETE_START(const_cast<char>(thd->query().str));
  23. bool res = mysql_delete(thd, unit->select_limit_cnt);
  24. MYSQL_DELETE_DONE(res, (ulong) thd->get_row_count_func());
  25. /

  26. /直接返回true/
  27. bool res =true;

  28. / Pop ignore / strict error handler */
  29. if (thd->lex->is_ignore() || thd->is_strict_mode())
  30. thd->pop_internal_handler();

  31. return res;
  32. }

然后上文的方法去重新编译mysql,启动后就会发现delete语句无法删除数据了。

调试总结

如果想深入学习源码,就可以从栈帧出发,但是这是基于知道函数接口功能的前提下进行的,如果不知道某个功能会调用什么函数,断点调试就很难进行了。

直接去读完 mysql 所有源码,成本太高,而且 mysql 的代码结构并不友好,耗时耗力不值得。最好的方案还是遇到问题时或针对特殊的一个功能点按需去寻找函数入口,然后逐步深入分析。

希望这篇文章可以帮到想接触mysql源码调试的同学,以后我遇到特殊的问题也会通过gdb去调试涉及的相关函数,大家可以持续关注~


全文完。


Enjoy MySQL :)

            </div>
相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
相关文章
|
SQL NoSQL 关系型数据库
利用GDB调试 MSQL(2)
利用GDB调试 MSQL
|
NoSQL 关系型数据库 MySQL
利用GDB调试 MSQL(1)
利用GDB调试 MSQL
224 0
利用GDB调试 MSQL(1)
|
16小时前
|
存储 关系型数据库 MySQL
数据管理的艺术:PolarDB开源版详评与实战部署策略(一)
PolarDB-X是阿里巴巴自研的高性能云原生分布式数据库,基于共享存储的Shared-nothing架构,支持MySQL生态,具备金融级高可用、分布式水平扩展、HTAP混合负载等能力。它通过CN(计算节点)和DN(存储节点)实现计算与存储分离,保证数据强一致性,并支持全局二级索引和多主多写。PolarDB-X开源版提供更高程度的定制化和控制权,适合追求技术自主性和成本优化的开发者。部署方式包括RPM包、PXD工具和Kubernetes,其中PXD工具提供了一键部署的便利性。
30585 10
|
4天前
|
关系型数据库 Serverless 分布式数据库
高峰无忧,探索PolarDB PG版Serverless的弹性魅力
在数字经济时代,数据库成为企业命脉,面对爆炸式增长的数据,企业面临管理挑战。云原生和Serverless技术革新数据库领域,PolarDB PG Serverless作为阿里云的云原生数据库解决方案,融合Serverless与PostgreSQL,实现自动弹性扩展,按需计费,降低运维成本。它通过计算与存储分离技术,提供高可用性、灾备策略和简化运维。PolarDB PG Serverless智能应变业务峰值,实时监控与调整资源,确保性能稳定。通过免费体验,用户可观察其弹性性能和价格力,感受技术优势。
|
14天前
|
存储 缓存 监控
你的Redis真的变慢了吗?性能优化如何做
本文先讲述了Redis变慢的判别方法,后面讲述了如何提升性能。
102210 3
|
14天前
|
机器学习/深度学习 并行计算 算法
Transformer 一起动手编码学原理
学习Transformer,快来跟着作者动手写一个。
94245 7
|
13天前
|
存储 SQL Apache
阿里云数据库内核 Apache Doris 基于 Workload Group 的负载隔离能力解读
阿里云数据库内核 Apache Doris 基于 Workload Group 的负载隔离能力解读
阿里云数据库内核 Apache Doris 基于 Workload Group 的负载隔离能力解读
|
19天前
|
人工智能 弹性计算 算法
一文解读:阿里云AI基础设施的演进与挑战
对于如何更好地释放云上性能助力AIGC应用创新?“阿里云弹性计算为云上客户提供了ECS GPU DeepGPU增强工具包,帮助用户在云上高效地构建AI训练和AI推理基础设施,从而提高算力利用效率。”李鹏介绍到。目前,阿里云ECS DeepGPU已经帮助众多客户实现性能的大幅提升。其中,LLM微调训练场景下性能最高可提升80%,Stable Difussion推理场景下性能最高可提升60%。
123944 18
|
14天前
|
存储 弹性计算 Cloud Native
1 名工程师轻松管理 20 个工作流,创业企业用 Serverless 让数据处理流程提效
为应对挑战,语势科技采用云工作流CloudFlow和函数计算FC,实现数据处理流程的高效管理与弹性伸缩,提升整体研发效能。
64729 2
|
20天前
|
消息中间件 安全 API
Apache RocketMQ ACL 2.0 全新升级
RocketMQ ACL 2.0 不管是在模型设计、可扩展性方面,还是安全性和性能方面都进行了全新的升级。旨在能够为用户提供精细化的访问控制,同时,简化权限的配置流程。欢迎大家尝试体验新版本,并应用在生产环境中。
187507 10