Pre-season
MYSQL source code reading one
MYSQL source code reading two
MYSQL source code reading three
MYSQL source code reading four
MYSQL source code reading five
I didn’t understand two questions last time
1 Why must the debugging thread be turned on? Because MYSQL is a threading model, you can also debug the entire MYSQLD service process
To use GDB, you must first set a breakpoint. MYSQLD encounters a breakpoint and all threads and services stop. For this reason, you don't need to debug the thread.
But we want to track the execution flow of a thread, which functions are executed? If the debugging process cannot be caught,
2 Why didn't the code in IF(RC) {...} be executed? I was tossing for a while, and then I thought of it a few days later and it was estimated that it did not meet the RC conditions
[root@localhost ~]# gdp -p 6041
(gdb) b do_command
Breakpoint 1 at 0x3616c8e: file /u01/mysql/source/mysql-8.0.20/sql/sql_parse.cc, line 1161.
(gdb) n
Single stepping until exit from function poll,
which has no line number information.
GDB is dead!
Kill GDB again, restart the system at most
Debug window:
(gdb) b do_command
Breakpoint 1 at 0x3616c8e: file /u01/mysql/source/mysql-8.0.20/sql/sql_parse.cc, line 1161.
(gdb) c
Continuing.
MySQL client window:
mysql> select * from books;
Debug window:
[Switching to Thread 0x7f1f940f5700 (LWP 3398)]
Breakpoint 1, do_command (thd=0x7f1f6c006790)
at /u01/mysql/source/mysql-8.0.20/sql/sql_parse.cc:1161
1161 NET *net = nullptr;
## What do you mean?
info thread
* 2 Thread 0x7f1f940f5700 (LWP 3398) "mysqld" do_command (thd=0x7f1f6c006790)
Understood! When GDB is debugging the service process, after setting the breakpoint function, the client sends an SQL request, and GDB is in a dead state at this time.
For this reason, after setting a breakpoint, enter the C command to let GDB continue. Then let the client send an SQL request, then GDB triggers the breakpoint function, and automatically switches to the thread, and stops the 1161 line, as long as N is The command can be tracked down!
This saves us the trouble of checking the client's processes, threads, and OS threads! But in a production environment, that is, when multiple users issue SQL statements at the same time, this method is estimated to be difficult.
But for us to learn the kernel source code, there are not so many concurrent client operations!
Source code:
1158 bool do_command(THD *thd) {
1159 bool return_value;
1160 int rc;
1161 NET *net = nullptr;
1162 enum enum_server_command command;
1163 COM_DATA com_data;
1164 DBUG_TRACE;
1165 DBUG_ASSERT(thd->is_classic_protocol());
Then all the way sparks bring lightning N down, and when I meet RC P, the result is really 0
(gdb) n
1164 DBUG_TRACE;
(gdb) n
1165 DBUG_ASSERT(thd->is_classic_protocol());
(gdb) n
1171 thd->lex->set_current_select(nullptr);
(gdb) n
1179 thd->clear_error(); // Clear error message
(gdb) n
1180 thd->get_stmt_da()->reset_diagnostics_area();
(gdb) n
1188 net = thd->get_protocol_classic()->get_net();
(gdb) n
1189 my_net_set_read_timeout(net, thd->variables.net_wait_timeout);
(gdb) n
1190 net_new_transaction(net);
(gdb) n
1206 DEBUG_SYNC(thd, "before_do_command_net_read");
(gdb) n
1219 thd->m_server_idle = true;
(gdb) n
1220 rc = thd->get_protocol()->get_command(&com_data, &command);
(gdb) n
1221 thd->m_server_idle = false;
(gdb) n
1223 if (rc) {
(gdb) p rc
$1 = 0
(gdb) n
1256 vio_description(net->vio, desc);
(gdb) n
1257 DBUG_PRINT("info", ("Command on %s = %d (%s)", desc, command,
(gdb) n
1260 DBUG_PRINT("info", ("packet: '%*.s'; command: %d",
(gdb) n
1263 if (thd->get_protocol_classic()->bad_packet)
(gdb) n
1267 thd->get_protocol_classic()->get_output_packet()->shrink(
(gdb) n
1268 thd->variables.net_buffer_length);
(gdb) n
1270 my_net_set_read_timeout(net, thd->variables.net_read_timeout);
(gdb) n
1272 DEBUG_SYNC(thd, "before_command_dispatch");
(gdb) n
1274 return_value = dispatch_command(thd, &com_data, command);
(gdb) n
1275 thd->get_protocol_classic()->get_output_packet()->shrink(
(gdb) n
1276 thd->variables.net_buffer_length);
(gdb) n
1280 DBUG_ASSERT(thd->m_digest == nullptr);
(gdb) n
1281 DBUG_ASSERT(thd->m_statement_psi == nullptr);
(gdb) n
1282 return return_value;
(gdb) n
1164 DBUG_TRACE;
(gdb) n
1282 return return_value;
(gdb) n
1283 }
(gdb) n
handle_connection (arg=0xa739020)
at /u01/mysql/source/mysql-8.0.20/sql/conn_handler/connection_handler_per_thread.cc:301
301 while (thd_connection_alive(thd)) {
After the function on line 1275 1276 is executed, the client receives the data
Breakpoint 1, do_command (thd=0x7f1f6c006790)
at /u01/mysql/source/mysql-8.0.20/sql/sql_parse.cc:1161
1161 NET *net = nullptr;
(gdb) n
1164 DBUG_TRACE;
(gdb) n
1165 DBUG_ASSERT(thd->is_classic_protocol());
(gdb) n
1171 thd->lex->set_current_select(nullptr);
(gdb) n
1179 thd->clear_error(); // Clear error message
(gdb) n
1180 thd->get_stmt_da()->reset_diagnostics_area();
(gdb) n
1188 net = thd->get_protocol_classic()->get_net();
(gdb) n
1189 my_net_set_read_timeout(net, thd->variables.net_wait_timeout);
(gdb) n
1190 net_new_transaction(net);
(gdb) n
1206 DEBUG_SYNC(thd, "before_do_command_net_read");
(gdb) n
1219 thd->m_server_idle = true;
(gdb) n
1220 rc = thd->get_protocol()->get_command(&com_data, &command);
(gdb) n
1221 thd->m_server_idle = false;
(gdb) n
1223 if (rc) {
(gdb) n
1256 vio_description(net->vio, desc);
(gdb) n
1257 DBUG_PRINT("info", ("Command on %s = %d (%s)", desc, command,
(gdb) n
1260 DBUG_PRINT("info", ("packet: '%*.s'; command: %d",
(gdb) n
1263 if (thd->get_protocol_classic()->bad_packet)
(gdb) n
1267 thd->get_protocol_classic()->get_output_packet()->shrink(
(gdb) n
1268 thd->variables.net_buffer_length);
(gdb) n
1270 my_net_set_read_timeout(net, thd->variables.net_read_timeout);
(gdb) n
1272 DEBUG_SYNC(thd, "before_command_dispatch");
(gdb) n
1274 return_value = dispatch_command(thd, &com_data, command);
(gdb) p thd
$17 = (THD *) 0x7f1f6c006790
(gdb) p com_data
$18 = {com_init_db = {db_name = 0x7f1f6c00bbe1 "select * from books", length = 19},
com_refresh = {options = 225 '\341'}, com_kill = {id = 139772932701153},
com_set_option = {opt_command = 1811987425}, com_stmt_execute = {
stmt_id = 139772932701153, open_cursor = 19, parameters = 0x7f1f6c00bbe8,
parameter_count = 139772932688388, has_new_types = 32 ' '}, com_stmt_fetch = {
stmt_id = 139772932701153, num_rows = 19}, com_stmt_send_long_data = {
stmt_id = 139772932701153, param_number = 19, longdata = 0x7f1f6c00bbe8 "* from books",
length = 139772932688388}, com_stmt_prepare = {
query = 0x7f1f6c00bbe1 "select * from books", length = 19}, com_stmt_close = {
stmt_id = 1811987425}, com_stmt_reset = {stmt_id = 1811987425}, com_query = {
query = 0x7f1f6c00bbe1 "select * from books", length = 19}, com_field_list = {
table_name = 0x7f1f6c00bbe1 "select * from books", table_name_length = 19,
query = 0x7f1f6c00bbe8 "* from books", query_length = 1811974660}}
(gdb) p command
$19 = COM_QUERY
(gdb) n
1275 thd->get_protocol_classic()->get_output_packet()->shrink(
(gdb) n
1276 thd->variables.net_buffer_length);
Dispatch_command(thd, &com_data, command); in line 1274 is this a command dispatcher?
THD is estimated to be a thread, COM_DATA is a command packet, and COMMAND is a command type