内容简介:在通过
背景
在 https://mengkang.net/1328.html 实验中,我们通过 optimizer_trace
发现 group by
会使用 intermediate_tmp_table
,而且里面的的 row_length
是20,抱着"打破砂锅问到底"的求学精神,所以想通过 gdb 调试源码的方式看这个 row_length
为什么是20.
通过 row_length
关键字,我定位到了 mysql 5.7 源码里面的 sql/sql_tmp_table.cc
文件
实际操作
查找 mysql pid
[root@localhost ~]# ps -ef|grep mysql root 3739 1 0 09:36 ? 00:00:00 /bin/sh /usr/local/mysql/bin/mysqld_safe --datadir=/var/lib/mysql --pid-file=/var/lib/mysql/localhost.localdomain.pid mysql 3894 3739 0 09:36 ? 00:00:01 /usr/local/mysql/bin/mysqld --basedir=/usr/local/mysql --datadir=/var/lib/mysql --plugin-dir=/usr/local/mysql/lib/plugin --user=mysql --log-error=/var/log/mariadb/mariadb.log --pid-file=/var/lib/mysql/localhost.localdomain.pid --socket=/var/lib/mysql/mysql.sock root 3956 3940 0 09:48 pts/1 00:00:00 mysql -uroot -px xxxx root 4002 3985 0 10:11 pts/2 00:00:00 grep --color=auto mysql
启动 gdb
[root@localhost ~]# gdb GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-114.el7 Copyright (C) 2013 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/>.
attach pid
(gdb) attach 3894
设置断点
(gdb) b trace_tmp_table Breakpoint 1 at 0x15e1eeb: file /root/newdb/mysql-server/sql/sql_tmp_table.cc, line 2300.
或者
(gdb) b /root/newdb/mysql-server/sql/sql_tmp_table.cc:2306 Breakpoint 1 at 0x15e1f8e: file /root/newdb/mysql-server/sql/sql_tmp_table.cc, line 2306.
客户端连接
[root@localhost ~]# mysql -uroot -p123456 test mysql: [Warning] Using a password on the command line interface can be insecure.
阻塞中
打印 backtrace
(gdb) bt #0 0x00007effcf4ec20d in poll () from /lib64/libc.so.6 #1 0x0000000001667759 in Mysqld_socket_listener::listen_for_connection_event (this=0x42e6360) at /root/newdb/mysql-server/sql/conn_handler/socket_connection.cc:852 #2 0x0000000000eb14fc in Connection_acceptor<Mysqld_socket_listener>::connection_event_loop (this=0x42ea0a0) at /root/newdb/mysql-server/sql/conn_handler/connection_acceptor.h:66 #3 0x0000000000ea8f7a in mysqld_main (argc=12, argv=0x41a60e8) at /root/newdb/mysql-server/sql/mysqld.cc:5149 #4 0x0000000000ea00ed in main (argc=8, argv=0x7ffece17c7e8) at /root/newdb/mysql-server/sql/main.cc:25
因为主进程在 poll 一直在等待客户端连接请求。
执行 continue
(gdb) c Continuing.
此时,mysql 客户端则进入 mysql 命令行界面
[root@localhost ~]# mysql -uroot -p123456 test mysql: [Warning] Using a password on the command line interface can be insecure. Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 3 Server version: 5.7.25-debug Source distribution Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql>
客户端执行查询
SET optimizer_trace='enabled=on'; select aid,sum(pv) as num from article_rank force index(idx_day_aid_pv) where day>20181223 group by aid order by num desc LIMIT 10;
查看断点处信息
[Switching to Thread 0x7f7f20145700 (LWP 4392)] Breakpoint 1, trace_tmp_table (trace=0x7eff94003088, table=0x7eff94937200) at /root/newdb/mysql-server/sql/sql_tmp_table.cc:2306 warning: Source file is more recent than executable. 2306 trace_tmp.add("row_length",table->s->reclength). (gdb) p table->s->reclength $1 = 20 (gdb) p table->s->fields $2 = 2 (gdb) p (*(table->field+0))->field_name $3 = 0x7eff94010b0c "aid" (gdb) p (*(table->field+1))->field_name $4 = 0x7eff94007518 "num" (gdb) p (*(table->field+0))->row_pack_length() $5 = 4 (gdb) p (*(table->field+1))->row_pack_length() $6 = 15 (gdb) p (*(table->field+0))->type() $7 = MYSQL_TYPE_LONG (gdb) p (*(table->field+1))->type() $8 = MYSQL_TYPE_NEWDECIMAL (gdb)
总结
原来和 group by
没关系,只因为我 sql 种使用了 sum
行数,使得 num
字段类型是 MYSQL_TYPE_NEWDECIMAL
The SUM() and AVG() functions return a DECIMAL value for exact-value arguments (integer or DECIMAL), and a DOUBLE value for approximate-value arguments (FLOAT or DOUBLE). (Before MySQL 5.0.3, SUM() and AVG() return DOUBLE for all numeric arguments.)
但是通过我们上面打印信息可以看到两个字段的长度加起来是 19
,而 reclength
是20。通过其他实验也发现 table->s->reclength
的长度就是 table->field
数组里面所有字段的字段长度和再加1。
附录
完整的 gdb 调试信息如下
[root@localhost ~]# gdb GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-114.el7 Copyright (C) 2013 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 3894 Attaching to process 3894 Reading symbols from /usr/local/mysql/bin/mysqld...done. Reading symbols from /lib64/libpthread.so.0...(no debugging symbols found)...done. [New LWP 4392] [New LWP 4368] [New LWP 4367] [New LWP 4366] [New LWP 4365] [New LWP 4364] [New LWP 4363] [New LWP 4362] [New LWP 4361] [New LWP 4360] [New LWP 4359] [New LWP 4358] [New LWP 4357] [New LWP 4356] [New LWP 4355] [New LWP 4353] [New LWP 4352] [New LWP 4351] [New LWP 4350] [New LWP 4349] [New LWP 4348] [New LWP 4347] [New LWP 4346] [New LWP 4345] [New LWP 4344] [New LWP 4343] [New LWP 4342] [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 0x00007f7f2c32620d in poll () from /lib64/libc.so.6 Missing separate debuginfos, use: debuginfo-install glibc-2.17-260.el7.x86_64 libgcc-4.8.5-36.el7.x86_64 libstdc++-4.8.5-36.el7.x86_64 nss-softokn-freebl-3.36.0-5.el7_5.x86_64 (gdb) b /root/newdb/mysql-server/sql/sql_tmp_table.cc:2306 Breakpoint 1 at 0x15e1f8e: file /root/newdb/mysql-server/sql/sql_tmp_table.cc, line 2306. (gdb) bt #0 0x00007f7f2c32620d in poll () from /lib64/libc.so.6 #1 0x0000000001667759 in Mysqld_socket_listener::listen_for_connection_event (this=0x3841360) at /root/newdb/mysql-server/sql/conn_handler/socket_connection.cc:852 #2 0x0000000000eb14fc in Connection_acceptor<Mysqld_socket_listener>::connection_event_loop (this=0x38450a0) at /root/newdb/mysql-server/sql/conn_handler/connection_acceptor.h:66 #3 0x0000000000ea8f7a in mysqld_main (argc=12, argv=0x37010e8) at /root/newdb/mysql-server/sql/mysqld.cc:5149 #4 0x0000000000ea00ed in main (argc=8, argv=0x7ffdaf5bc2e8) at /root/newdb/mysql-server/sql/main.cc:25 (gdb) c Continuing. [Switching to Thread 0x7f7f20145700 (LWP 4392)] Breakpoint 1, trace_tmp_table (trace=0x7f7ef8016b18, table=0x7f7ef8937380) at /root/newdb/mysql-server/sql/sql_tmp_table.cc:2306 warning: Source file is more recent than executable. 2306 trace_tmp.add("row_length",table->s->reclength). (gdb) p table->s->reclength $1 = 20 (gdb) p table->s->fields $2 = 2 (gdb) p (*(table->field+0))->field_name $3 = 0x7eff94010b0c "aid" (gdb) p (*(table->field+1))->field_name $4 = 0x7eff94007518 "num" (gdb) p (*(table->field+0))->row_pack_length() $5 = 4 (gdb) p (*(table->field+1))->row_pack_length() $6 = 15 (gdb) p (*(table->field+0))->type() $7 = MYSQL_TYPE_LONG (gdb) p (*(table->field+1))->type() $8 = MYSQL_TYPE_NEWDECIMAL (gdb)
以上所述就是小编给大家介绍的《GDB 调试 Mysql 实战(二)GDB 调试打印》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Go语言实战笔记(二十三)| Go 调试
- 《Java8实战》-第八章笔记(重构、测试和调试)
- GDB 调试 Mysql 实战(三)优先队列排序算法中的行记录长度统计是怎么来的(上)
- GDB 调试 Mysql 实战(三)优先队列排序算法中的行记录长度统计是怎么来的(下)
- iOS常用调试方法:断点调试
- 断点调试和日志调试之间的平衡点:函数计算调试之 Python 篇
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
流畅的Python
[巴西] Luciano Ramalho / 安道、吴珂 / 人民邮电出版社 / 2017-5-15 / 139元
【技术大咖推荐】 “很荣幸担任这本优秀图书的技术审校。这本书能帮助很多中级Python程序员掌握这门语言,我也从中学到了相当多的知识!”——Alex Martelli,Python软件基金会成员 “对于想要扩充知识的中级和高级Python程序员来说,这本书是充满了实用编程技巧的宝藏。”——Daniel Greenfeld和Audrey Roy Greenfeld,Two Scoops ......一起来看看 《流畅的Python》 这本书的介绍吧!