Tools | common MySQL kernel debugging skills

Author: Ke Yuchang consultant Software Engineer

Currently engaged in container R & D of RadonDB MySQL, graduated from Huazhong University of science and technology, and has many years of experience in database kernel development.

Mastering the reading and debugging ability of MySQL kernel source code is not only the daily work of database R & D personnel, but also the only way for DBA to advance.

Read this article and you will learn:

  • How to prepare MySQL debugging environment
  • Introduction to GDB debugging and operation examples
  • Trace file debugging and operation examples

|1, Prepare the Debug environment

First, compile and install a MySQL environment for debugging with the source code.

Open - DWITH_DEBUG, create the build directory in the source code path, enter the directory and execute:

cmake .. -DWITH_BOOST=../../boost -DWITH_DEBUG=1

Then confirm whether the compilation is successful by the following methods.

Mode 1:

$ ./bin/mysqld --verbose --version

If the debug version information is echoed, the debug version is compiled.

ver 8.0.18-debug for Linux on x86_64 (Source distribution)

Mode 2:

Connect to the database and execute the view version command. If the echo contains the word debug, the debug version is compiled.

$ mysql> select version();
+--------------+
| version()    |
+--------------+
| 8.0.18-debug |
+--------------+
1 row in set (0.00 sec)

|2, Debugging with GDB

The full name of gdb is "GNU symbolic debugger". It is a commonly used program debugger under Linux. It is usually used in the terminal (Shell) in the form of gdb command.

Start GDB compiler

Execute the following command to start the GDB compiler (assuming my.cnf is in the user's root directory). After entering GDB, type run to run.

gdb --args ./bin/mysqld --defaults-file=~/my.cnf --gdb

The -- gdb parameter allows you to interrupt the mysqld process by Ctrl+C at any time for debugging commands.

GDB common commands

Readers who use multiple windows to view the source code and debugging can use the layout command. Execute help layout in gdb to view more gdb command usage.

(gdb) help layout
(gdb) help layoutChange the layout of windows.
Usage: layout prev | next | <layout_name>
Layout names are:
   src   : Displays source and command windows.
   asm   : Displays disassembly and command windows.
   split : Displays source, disassembly and command windows.
   regs  : Displays register window. If existing layout
           is source/command or assembly/command, the
           register window is displayed. If the
           source/assembly/command (split) is displayed,
           the register window is displayed with
           the window that has current logical focus.

(gdb)

You can learn more about the use of GDB through GDB cheat sheet[1].

Debug example

After installing the Debug environment, let's use the following two examples to briefly demonstrate the ideas and skills.

1. Take variable value

In some cases, it is found that mysqld has crash ed, the system has only one core file, and we need to know the value of a system variable. But the value of the system variable is not necessarily the same as my CNF file is consistent.

At this point, you can print the variable with the gdb command to obtain the variable value.

As shown below, to get the value of the variable version, just add MySQL in front of it_ sysvar_ Just print the prefix.

Thread 1 "mysqld" received signal SIGINT, Interrupt.
0x00007ffff5f74cb9 in __GI___poll (fds=0x55555e8a3de0, nfds=2, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:29
29    ../sysdeps/unix/sysv/linux/poll.c: No such file or directory.
(gdb) p mysql_sysvar_version
$1 = {flags = 68101, name = 0x55555e7ff738 "innodb_version", comment = 0x55555ca953e2 "InnoDB version", check = 0x555558e222f1 <check_func_str(THD*, SYS_VAR*, void*, st_mysql_value*)>, update = 0x555558e22881 <update_func_str(THD*, SYS_VAR*, void*, void const*)>,
  value = 0x55555def1c20 <innodb_version_str>, def_val = 0x55555ca89598 "8.0.18"}
(gdb)

2. Debug script

Suppose you need to obtain a connection to enter the dispatch_command, which commands can be obtained by executing gdb script [2].

The gdb script is as follows:

b dispatch_command
commands
    print command
    continue
end

Execute the gdb script, then use the mysql client to connect to the database and execute the SQL statement operation to view the gdb debugging information.

(gdb) b dispatch_command
Breakpoint 3 at 0x555558ddb37c: file /home/kyc/mysql8/sql/sql_parse.cc, line 1581.
(gdb) commands
Type commands for breakpoint(s) 3, one per line.
End with a line saying just "end".
>print command
>continue
>end
(gdb) c
Continuing.
[Switching to Thread 0x7fffe01fc700 (LWP 5941)]

Thread 49 "mysqld" hit Breakpoint 3, dispatch_command (thd=0x7fff4c000f70, com_data=0x7fffe01fbba0, command=COM_QUERY) at /home/kyc/galaxyengine/sql/sql_parse.cc:1581
1581                          enum enum_server_command command) {
$4 = COM_QUERY

|3, Debugging using Trace files

The debug version of MySQL provides a special DBUG package [3]. Through this DBUG package, you can obtain the Trace file of the operating program being executed.

By controlling the DBUG switch, you can record any operation of MySQL, as well as the related calling modules, functions and status information in the Trace file.

Set debug parameters

Specify the tracking method by setting the debug parameter option.

--debug [ = debug_options ]

[= debug options] can recognize characters d, t, i, o, etc.

Debug example

To get the dbug in the code_ For the log printed by print ("Info:"), you can use the MySQL client to connect to the server and execute the following command to enable the debug parameter.

set debug = 'd,info';
use test;

View mysqld Trace file to obtain the execution process of use test in MySQL.

do_command: info: Command on socket (46) = 3 (Query)
do_command: info: packet: '                 '; command: 3
dispatch_command: info: command: 3
gtid_pre_statement_checks: info: gtid_next->type=0 owned_gtid.{sidno,gno}={0,0}
THD::is_ddl_gtid_compatible: info: SQLCOM_CREATE:0 CREATE-TMP:0 SELECT:1 SQLCOM_DROP:0 DROP-TMP:0 trx:0
SELECT_LEX::prepare: info: setup_ref_array this 0x7fff1400d298    3 :    0    0    1    2    0    0
setup_fields: info: thd->mark_used_columns: 1
setup_fields: info: thd->mark_used_columns: 1
SELECT_LEX::setup_conds: info: thd->mark_used_columns: 1
THD::decide_logging_format: info: query: SELECT DATABASE()
THD::decide_logging_format: info: variables.binlog_format: 2
................
MDL_context::release_locks_stored_before: info: found lock to release ticket=0x7fff14019ae0
MDL_context::release_locks_stored_before: info: found lock to release ticket=0x7fff1412dd20
MDL_context::release_locks_stored_before: info: found lock to release ticket=0x7fff1412dcc0
net_send_ok: info: affected_rows: 0  id: 0  status: 2  warning_count: 0
net_send_ok: info: OK sent, so no more error sending allowed

This article uses several simple examples to demonstrate several common methods of debugging MySQL kernel. Of course, it only plays the role of throwing bricks and attracting jade. More interesting skills need to be deeply excavated by readers themselves.

reference resources

[1]: GDB cheat sheet: https://gist.github.com/rkubik/b96c23bd8ed58333de37f2b8cd052c30

[2]: GDB script debugging: https://sourceware.org/gdb/current/onlinedocs/gdb/Commands.html#Commands

[3]: DBUG Package[: https://dev.mysql.com/doc/refman/8.0/en/dbug-package.html

Keywords: GDB

Added by pepperface on Fri, 17 Dec 2021 21:27:02 +0200