Pretemporada
Código fuente MYSQL leyendo uno
Código fuente de MYSQL leyendo dos
Código fuente de MYSQL leyendo tres
Código fuente de MYSQL leyendo cuatro
Código fuente de MYSQL leyendo cinco
No entendí dos preguntas la última vez
1 ¿Por qué se debe activar el subproceso de depuración? Dado que MYSQL es un modelo de subprocesamiento, también puede depurar todo el proceso del servicio MYSQLD
Para utilizar GDB, primero debe establecer un punto de interrupción. MYSQLD encuentra un punto de interrupción y todos los subprocesos y servicios se detienen. Por esta razón, no es necesario depurar el subproceso.
Pero queremos rastrear el flujo de ejecución de un hilo, ¿qué funciones se ejecutan? Si el proceso de depuración no se puede capturar,
2 ¿Por qué no se ejecutó el código en IF (RC) {...}? Estuve lanzando un rato, y luego lo pensé unos días después y se estimó que no cumplía con las condiciones de RC
[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 está muerto!
Mata GDB de nuevo, reinicia el sistema como máximo
Ventana de depuración:
(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.
Ventana del cliente MySQL:
mysql> select * from books;
Ventana de depuración:
[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;
## ¿Qué quieres decir?
info thread
* 2 Thread 0x7f1f940f5700 (LWP 3398) "mysqld" do_command (thd=0x7f1f6c006790)
Entendido Cuando GDB está depurando el proceso de servicio, después de configurar la función de punto de interrupción, el cliente envía una solicitud SQL y GDB está en un estado inactivo en este momento.
Por esta razón, después de establecer un punto de interrupción, ingrese el comando C para permitir que GDB continúe. Luego, deje que el cliente envíe una solicitud SQL, luego GDB activa la función de punto de interrupción, cambia automáticamente al hilo y detiene la línea 1161, siempre que N es ¡El comando se puede rastrear!
¡Esto nos ahorra la molestia de verificar el proceso, el hilo y el hilo del sistema operativo del cliente! Sin embargo, en un entorno de producción, es decir, cuando varios usuarios emiten sentencias SQL al mismo tiempo, se estima que este método es difícil.
Pero para que aprendamos el código fuente del kernel, ¡no hay tantas operaciones de cliente concurrentes!
Código fuente:
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());
Luego chispas y relámpagos N hasta el final, cuando conocí a RC P, el resultado fue realmente 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)) {
Después de que se ejecuta la función en la línea 1275 1276, el cliente recibe los datos
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); en la línea 1274, ¿es este un despachador de comandos?
Se estima que THD es un subproceso, COM_DATA es un paquete de comando y COMMAND es un tipo de comando