Lectura de código fuente MYSQL 6

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

Supongo que te gusta

Origin blog.51cto.com/15080028/2643041
Recomendado
Clasificación