在下面函数上打上断点。
Protocol_classic::read_packet()
Protocol_classic::send_ok
do_command
Protocol_classic::get_command
dispatch_command
Protocol_classic::start_result_metadata
Protocol_classic::store_string
THD::send_result_set_row
Item::send
my_net_read
启动gdb
[root@ecs-test-node2 ~]# gdb -p $(pgrep -x mysqld)
(gdb) b Protocol_classic::read_packet()
Breakpoint 1 at 0x3ce2d10: file /data/mysql-8.0.42/sql/protocol_classic.cc, line 1410.
(gdb) b Protocol_classic::send_ok
Breakpoint 2 at 0x3ce2775: file /data/mysql-8.0.42/sql/protocol_classic.cc, line 1300.
(gdb) b do_command
Breakpoint 3 at 0x361c022: file /data/mysql-8.0.42/sql/sql_parse.cc, line 1311.
(gdb) b Protocol_classic::get_command
Breakpoint 4 at 0x3ce4002: file /data/mysql-8.0.42/sql/protocol_classic.cc, line 2993.
(gdb) b dispatch_command
Breakpoint 5 at 0x361cfbd: file /data/mysql-8.0.42/sql/sql_parse.cc, line 1690.
(gdb) b Protocol_classic::start_result_metadata
Breakpoint 6 at 0x3ce43c3: file /data/mysql-8.0.42/sql/protocol_classic.cc, line 3081.
(gdb) b Protocol_classic::store_string
Breakpoint 7 at 0x3ce50a3: file /data/mysql-8.0.42/sql/protocol_classic.cc, line 3425.
(gdb) b THD::send_result_set_row
Breakpoint 8 at 0x352fffa: file /data/mysql-8.0.42/sql/sql_class.cc, line 2887.
(gdb) b Item::send
Breakpoint 9 at 0x3a64ed7: file /data/mysql-8.0.42/sql/item.cc, line 7350.
(gdb) b my_net_read
Breakpoint 10 at 0x381aff3: file /data/mysql-8.0.42/sql-common/net_serv.cc, line 2268.
(gdb) info break
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000003ce2d10 in Protocol_classic::read_packet()
at /data/mysql-8.0.42/sql/protocol_classic.cc:1410
2 breakpoint keep y 0x0000000003ce2775 in Protocol_classic::send_ok(unsigned int, unsigned int, unsigned long long, unsigned long long, char const*) at /data/mysql-8.0.42/sql/protocol_classic.cc:1300
3 breakpoint keep y 0x000000000361c022 in do_command(THD*) at /data/mysql-8.0.42/sql/sql_parse.cc:1311
4 breakpoint keep y 0x0000000003ce4002 in Protocol_classic::get_command(COM_DATA*, enum_server_command*)
at /data/mysql-8.0.42/sql/protocol_classic.cc:2993
5 breakpoint keep y 0x000000000361cfbd in dispatch_command(THD*, COM_DATA const*, enum_server_command)
at /data/mysql-8.0.42/sql/sql_parse.cc:1690
6 breakpoint keep y 0x0000000003ce43c3 in Protocol_classic::start_result_metadata(unsigned int, unsigned int, CHARSET_INFO const*) at /data/mysql-8.0.42/sql/protocol_classic.cc:3081
7 breakpoint keep y 0x0000000003ce50a3 in Protocol_classic::store_string(char const*, unsigned long, CHARSET_INFO const*) at /data/mysql-8.0.42/sql/protocol_classic.cc:3425
8 breakpoint keep y 0x000000000352fffa in THD::send_result_set_row(mem_root_deque<Item*> const&)
at /data/mysql-8.0.42/sql/sql_class.cc:2887
9 breakpoint keep y 0x0000000003a64ed7 in Item::send(Protocol*, String*)
at /data/mysql-8.0.42/sql/item.cc:7350
10 breakpoint keep y 0x000000000381aff3 in my_net_read(NET*) at /data/mysql-8.0.42/sql-common/net_serv.cc:2268
在另外一个终端,使用mysql连接DB。
[root@ecs-test-node2 ~]# mysql -h 192.168.0.100 -P 3315 -u lily -p -A
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
read_packet函数,用来读取客户端发过来的包。
(gdb) continue
Continuing.
[Switching to Thread 0x7f54a4268700 (LWP 1607978)]
Thread 35 "connection" hit Breakpoint 1, Protocol_classic::read_packet (this=0x7f542400c7f0)
at /data/mysql-8.0.42/sql/protocol_classic.cc:1410
1410 input_packet_length = my_net_read(&m_thd->net);
查看执行路径。
在login_connection建立连接后,会有native_password_authenticate等登陆验证的函数执行。
在parse_client_handshake_packet这个解析客户端握手包函数执行后,会来到read_packet函数。
(gdb) backtrace
#0 Protocol_classic::read_packet (this=0x7f542400c7f0) at /data/mysql-8.0.42/sql/protocol_classic.cc:1410
#1 0x00000000038d0a22 in parse_client_handshake_packet (thd=0x7f5424008990, mpvio=0x7f54a4267020, buff=0x7f54a4266b68,
pkt_len=32) at /data/mysql-8.0.42/sql/auth/sql_authentication.cc:2907
#2 0x00000000038d1b6f in server_mpvio_read_packet (param=0x7f54a4267020, buf=0x7f54a4266b68)
at /data/mysql-8.0.42/sql/auth/sql_authentication.cc:3358
#3 0x00000000038d554e in native_password_authenticate (vio=0x7f54a4267020, info=0x7f54a4267048)
at /data/mysql-8.0.42/sql/auth/sql_authentication.cc:4555
#4 0x00000000038d1d3e in do_auth_once (thd=0x7f5424008990, auth_plugin_name=..., mpvio=0x7f54a4267020)
at /data/mysql-8.0.42/sql/auth/sql_authentication.cc:3403
#5 0x00000000038d350a in acl_authenticate (thd=0x7f5424008990, command=COM_CONNECT)
at /data/mysql-8.0.42/sql/auth/sql_authentication.cc:3885
#6 0x0000000003594c53 in check_connection (thd=0x7f5424008990) at /data/mysql-8.0.42/sql/sql_connect.cc:652
#7 0x0000000003594e00 in login_connection (thd=0x7f5424008990) at /data/mysql-8.0.42/sql/sql_connect.cc:706
#8 0x0000000003595d29 in thd_prepare_connection (thd=0x7f5424008990) at /data/mysql-8.0.42/sql/sql_connect.cc:893
#9 0x000000000384457a in handle_connection (arg=0xc4025a0)
at /data/mysql-8.0.42/sql/conn_handler/connection_handler_per_thread.cc:299
#10 0x00000000058bf53d in pfs_spawn_thread (arg=0xc402390) at /data/mysql-8.0.42/storage/perfschema/pfs.cc:3050
#11 0x00007f54cde821ca in start_thread (arg=<optimized out>) at pthread_create.c:479
#12 0x00007f54cc3a18d3 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
查看变量
(gdb) info local
__PRETTY_FUNCTION__ = "virtual int Protocol_classic::read_packet()"
(gdb) in args
Ambiguous command "in args": inf, inferior, info, init-if-undefined, inspect, internals, interpreter-exec, interrupt.
(gdb) info args
this = 0x7f542c0508b0
(gdb) print * this
$1 = {<Protocol> = {_vptr.Protocol = 0x87d3238 <vtable for Protocol_text+16>, m_previous_protocol = 0x0},
m_client_capabilities = 3758096383, m_thd = 0x7f542c19a5a0, packet = 0x7f542c19c630, convert = {m_ptr = 0x0,
m_length = 0, m_charset = 0x88b7280 <my_charset_bin>, m_alloced_length = 0, m_is_alloced = false},
field_pos = 1751318644, send_metadata = false, field_types = 0x0, count = 1970496882, field_count = 7566444,
sending_flags = 1918986339, input_packet_length = 0,
input_raw_packet = 0x6e6f697463656e6e <error: Cannot access memory at address 0x6e6f697463656e6e>, result_cs = 0x0,
bad_packet = true}
查看packet包里面的内容
(gdb) print *this.packet
$2 = {m_ptr = 0x7f542c1aeeb0 "", m_length = 0, m_charset = 0x88b7280 <my_charset_bin>, m_alloced_length = 16392,
m_is_alloced = true}
(gdb) print *this->packet
$3 = {m_ptr = 0x7f542c1aeeb0 "", m_length = 0, m_charset = 0x88b7280 <my_charset_bin>, m_alloced_length = 16392,
m_is_alloced = true}
(gdb) print *this->packet.m_charset
$4 = {number = 63, primary_number = 0, binary_number = 0, state = 817, csname = 0x76437e0 "binary",
m_coll_name = 0x76437e0 "binary", comment = 0x76437e7 "Binary pseudo charset", tailoring = 0x0, coll_param = 0x0,
ctype = 0x76435c0 <ctype_bin> "", to_lower = 0x76436e0 <bin_char_array> "", to_upper = 0x76436e0 <bin_char_array> "",
sort_order = 0x0, uca = 0x0, tab_to_uni = 0x0, tab_from_uni = 0x0, caseinfo = 0x8a1c9e0 <my_unicase_default>,
state_maps = 0xc08f3d0, ident_map = 0xc08f5d0 "", strxfrm_multiply = 1, caseup_multiply = 1 '\001',
casedn_multiply = 1 '\001', mbminlen = 1, mbmaxlen = 1, mbmaxlenlen = 1, min_sort_char = 0, max_sort_char = 255,
pad_char = 0 '\000', escape_with_backslash_is_dangerous = false, levels_for_compare = 1 '\001',
cset = 0x88b71a0 <my_charset_handler>, coll = 0x88b7140 <my_collation_binary_handler>, pad_attribute = NO_PAD}
打印线程结构体
(gdb) print this->m_thd
$14 = (THD *) 0x7f542c19a5a0
(gdb) print *this->m_thd
$15 = {<MDL_context_owner> = {_vptr.MDL_context_owner = 0x86ecb00 <vtable for THD+16>}, <Query_arena> = {
_vptr.Query_arena = 0x86ecb70 <vtable for THD+128>, m_item_list = 0x0, mem_root = 0x7f542c19ced0,
is_repreparing = false, state = Query_arena::STMT_REGULAR_EXECUTION}, <Open_tables_state> = {
m_reprepare_observers = {static Has_trivial_destructor = <optimized out>, static initial_capacity = <optimized out>,
m_psi_key = 0, m_inline_size = 0, {m_ext = {m_array_ptr = 0x0, m_alloced_size = 0, m_alloced_capacity = 0},
m_buff = {0x0, 0x0, 0x0, 0x0}}}, open_tables = 0x0, temporary_tables = 0x0, lock = 0x0, extra_lock = 0x0,
locked_tables_mode = LTM_NONE, state_flags = 0}, m_mem_cnt = {m_enabled = true, m_thd = 0x7f542c19a5a0, m_da = {
m_stacked_da = 0x0, m_condition_root = {static s_dummy_target = 0 '\000', m_current_block = 0x0,
m_current_free_start = 0x8cb2350 <MEM_ROOT::s_dummy_target> "",
m_current_free_end = 0x8cb2350 <MEM_ROOT::s_dummy_target> "", m_block_size = 2048, m_orig_block_size = 2048,
m_max_capacity = 0, m_allocated_size = 0, m_error_for_capacity_exceeded = false, m_error_handler = 0x34f935d
<sql_alloc_error_handler()>, m_psi_key = 0}, m_conditions_list = {<I_P_List_counter> = {
m_counter = 0}, <I_P_List_fast_push_back<Sql_condition>> = {m_last = 0x7f542c19a690}, m_first = 0x0},
m_preexisting_sql_conditions = {<base_list> = {first = 0x8c08d70 <end_of_list>, last = 0x7f542c19a698,
elements = 0}, <No data fields>}, m_is_sent = false, m_can_overwrite_status = false,
m_allow_unlimited_conditions = false, m_status = Diagnostics_area::DA_EMPTY,
m_message_text = "\000d=1;row_type=2;stats_auto_recalc=0;stats_persistent=0;stats_sample_pages=0;\000\000\000\000", '\337' <repeats 16 times>, '\000' <repeats 415 times>, m_message_text_length = 0,
m_returned_sqlstate = "\000\000\000\000\000", m_mysql_errno = 0, m_affected_rows = 0, m_last_insert_id = 0,
m_last_statement_cond_count = 0, m_current_statement_cond_count = 0, m_current_statement_cond_count_by_qb = {0, 0,
0}, m_current_row_for_condition = 1, m_saved_error_count = 0, m_saved_warn_count = 0}, mem_counter = 8240,
max_conn_mem = 8240, glob_mem_counter = 0, curr_mode = 0, orig_mode = 0, is_connection_stage = true}, mdl_context = {
m_wait = {m_LOCK_wait_status = {m_mutex = {m_u = {m_native = {__data = {__lock = 739830096, __count = 32596,
__owner = 0, __nusers = 0, __kind = 0, __spins = 0, __elision = 0, __list = {__prev = 0x0,
__next = 0x0}}, __size = "P\351\030,T\177", '\000' <repeats 33 times>, __align = 139999493810512},
m_safe_ptr = 0x7f542c18e950}}, m_psi = 0xc21cfa0}, m_COND_wait_status = {m_cond = {__data = {{__wseq = 0,
__wseq32 = {__low = 0, __high = 0}}, {__g1_start = 0, __g1_start32 = {__low = 0, __high = 0}},
__glibc_unused___g_refs = {0, 0}, __g_size = {0, 0}, __g1_orig_size = 0, __wrefs = 0, __g_signals = {0, 0}},
__size = '\000' <repeats 47 times>, __align = 0}, m_psi = 0xc010c58}, m_wait_status = MDL_wait::WS_EMPTY},
m_ticket_store = {m_durations = {{
m_ticket_list = {<I_P_List_null_counter> = {<No data fields>}, <I_P_List_no_push_back<MDL_ticket>> = {<No data fields>}, m_first = 0x0}, m_mat_front = 0x0}, {
m_ticket_list = {<I_P_List_null_counter> = {<No data fields>}, <I_P_List_no_push_back<MDL_ticket>> = {<No data f--Type <RET> for more, q to quit, c to continue without paging--q
Quit
read_packet的函数定义
int Protocol_classic::read_packet() {
input_packet_length = my_net_read(&m_thd->net);
if (input_packet_length != packet_error) {
assert(!m_thd->net.error);
bad_packet = false;
input_raw_packet = m_thd->net.read_pos;
return 0;
}
bad_packet = true;
return m_thd->net.error == NET_ERROR_SOCKET_UNUSABLE ? 1 : -1;
}
继续调试后面的断点。
(gdb) continue
Continuing.
Thread 36 "connection" hit Breakpoint 10, my_net_read (net=0x7f542c19c398)
at /data/mysql-8.0.42/sql-common/net_serv.cc:2268
2268 if (!vio_is_blocking(net->vio)) vio_set_blocking_flag(net->vio, true);
(gdb) backtrace
#0 my_net_read (net=0x7f542c19c398) at /data/mysql-8.0.42/sql-common/net_serv.cc:2268
#1 0x0000000003ce2d26 in Protocol_classic::read_packet (this=0x7f542c0508b0)
at /data/mysql-8.0.42/sql/protocol_classic.cc:1410
#2 0x00000000038d1aec in server_mpvio_read_packet (param=0x7f54a4165020, buf=0x7f54a4164b68)
at /data/mysql-8.0.42/sql/auth/sql_authentication.cc:3344
#3 0x00000000038d554e in native_password_authenticate (vio=0x7f54a4165020, info=0x7f54a4165048)
at /data/mysql-8.0.42/sql/auth/sql_authentication.cc:4555
#4 0x00000000038d1d3e in do_auth_once (thd=0x7f542c19a5a0, auth_plugin_name=..., mpvio=0x7f54a4165020)
at /data/mysql-8.0.42/sql/auth/sql_authentication.cc:3403
#5 0x00000000038d350a in acl_authenticate (thd=0x7f542c19a5a0, command=COM_CONNECT)
at /data/mysql-8.0.42/sql/auth/sql_authentication.cc:3885
#6 0x0000000003594c53 in check_connection (thd=0x7f542c19a5a0) at /data/mysql-8.0.42/sql/sql_connect.cc:652
#7 0x0000000003594e00 in login_connection (thd=0x7f542c19a5a0) at /data/mysql-8.0.42/sql/sql_connect.cc:706
#8 0x0000000003595d29 in thd_prepare_connection (thd=0x7f542c19a5a0) at /data/mysql-8.0.42/sql/sql_connect.cc:893
#9 0x000000000384457a in handle_connection (arg=0xc448c60)
at /data/mysql-8.0.42/sql/conn_handler/connection_handler_per_thread.cc:299
#10 0x00000000058bf53d in pfs_spawn_thread (arg=0xc430ac0) at /data/mysql-8.0.42/storage/perfschema/pfs.cc:3050
#11 0x00007f54cde821ca in start_thread (arg=<optimized out>) at pthread_create.c:479
#12 0x00007f54cc3a18d3 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
my_net_read用于读取客户端/服务端发过来的包,返回的时候不带有内部的包头。
/**
Read a packet from the client/server and return it without the internal
package header.
*/
ulong my_net_read(NET *net) {
size_t len;
/* turn off non blocking operations */
if (!vio_is_blocking(net->vio)) vio_set_blocking_flag(net->vio, true);
if (net->compress)
net_read_compressed_packet(net, len);
else
net_read_uncompressed_packet(net, len);
return static_cast<ulong>(len);
}
查看net结构体。
(gdb) info local
len = 140001506904768
(gdb) info args
net = 0x7f542c19c398
(gdb) print *net
$16 = {vio = 0x7f542c050960, buff = 0x7f542c069700 "P", buff_end = 0x7f542c06d700 "0@", write_pos = 0x7f542c069700 "P",
read_pos = 0x6e6f697463656e6e <error: Cannot access memory at address 0x6e6f697463656e6e>, fd = 37, remain_in_buf = 0,
length = 0, buf_length = 0, where_b = 0, max_packet = 16384, max_packet_size = 1073741824, pkt_nr = 1,
compress_pkt_nr = 0, write_timeout = 10, read_timeout = 10, retry_count = 10, fcntl = 0, return_status = 0x0,
reading_or_writing = 0 '\000', save_char = 0 '\000', compress = false, last_errno = 0, error = 0 '\000',
last_error = '\000' <repeats 511 times>, sqlstate = "\000\000\000\000\000", extension = 0x7f542c19ab90}
(gdb) print *net.buff
$17 = 80 'P'
(gdb) print *net.buff_end
$18 = 48 '0'
(gdb) print *net.write_pos
$19 = 80 'P'
(gdb) print *net.vio
$20 = {mysql_socket = {fd = 37, m_psi = 0xc22aed8}, localhost = false, type = VIO_TYPE_TCPIP, read_timeout = 10000,
write_timeout = 10000, retry_count = 1, inactive = false, local = {ss_family = 0,
__ss_padding = '\000' <repeats 117 times>, __ss_align = 0}, remote = {ss_family = 2,
__ss_padding = "\241\062\300\250\000d", '\000' <repeats 111 times>, __ss_align = 0}, addrLen = 16,
read_buffer = 0x0, read_pos = 0x0, read_end = 0x0, thread_id = std::optional [no contained value], signal_mask = {
__val = {543239, 0 <repeats 15 times>}}, poll_shutdown_flag = {<std::__atomic_flag_base> = {
_M_i = false}, <No data fields>}, network_namespace = '\000' <repeats 255 times>, viodelete = 0x5c24a4b
<vio_delete(Vio*)>, vioerrno = 0x5c254d9 <vio_errno(Vio*)>,
read = 0x5c2558b <vio_read(Vio*, unsigned char*, unsigned long)>,
write = 0x5c259ba <vio_write(Vio*, unsigned char const*, unsigned long)>,
timeout = 0x5c25d6d <vio_socket_timeout(Vio*, unsigned int, bool)>,
viokeepalive = 0x5c25f56 <vio_keepalive(Vio*, bool)>, fastsend = 0x5c25e2a <vio_fastsend(Vio*)>,
peer_addr = 0x5c26779 <vio_peer_addr(Vio*, char*, unsigned short*, unsigned long)>, in_addr = 0x0,
should_retry = 0x5c2606e <vio_should_retry(Vio*)>, was_timeout = 0x5c2608e <vio_was_timeout(Vio*)>,
vioshutdown = 0x5c260e0 <vio_shutdown(Vio*)>, is_connected = 0x5c27160 <vio_is_connected(Vio*)>,
has_data = 0x5c2369c <has_no_data(Vio*)>, io_wait = 0x5c26af9 <vio_io_wait(Vio*, enum_vio_io_event, int)>,
connect = 0x0, ssl_arg = 0x0, m_psi_read_locker = 0x0, m_psi_read_state = {m_flags = 738528440, m_socket = 0x0,
m_thread = 0x7f530000004f, m_number_of_bytes = 0, m_timer_start = 0, m_timer = 0x7f542c050ce8,
m_operation = 738528488, m_src_file = 0x0, m_src_line = 800, m_wait = 0xb1}, m_psi_write_locker = 0x0,
m_psi_write_state = {m_flags = 739948384, m_socket = 0x7f54c5dafc40, m_thread = 0x91,
m_number_of_bytes = 1752346657176, m_timer_start = 0, m_timer = 0x7f54cd9af6e0 <eckey_asn1_meth>,
m_operation = PSI_SOCKET_CREATE, m_src_file = 0x0, m_src_line = 0, m_wait = 0x1},
is_blocking = 0x5c25d22 <vio_is_blocking(Vio*)>, set_blocking = 0x5c25b31 <vio_set_blocking(Vio*, bool)>,
set_blocking_flag = 0x5c25c28 <vio_set_blocking_flag(Vio*, bool)>, is_blocking_flag = true}
继续调试后续的代码。
(gdb) continue
Continuing.
Thread 36 "connection" hit Breakpoint 1, Protocol_classic::read_packet (this=0x7f542c0508b0)
at /data/mysql-8.0.42/sql/protocol_classic.cc:1410
1410 input_packet_length = my_net_read(&m_thd->net);
(gdb) info args
this = 0x7f542c0508b0
(gdb) c
Continuing.
Thread 36 "connection" hit Breakpoint 10, my_net_read (net=0x7f542c19c398)
at /data/mysql-8.0.42/sql-common/net_serv.cc:2268
2268 if (!vio_is_blocking(net->vio)) vio_set_blocking_flag(net->vio, true);
(gdb) c
Continuing.
Thread 36 "connection" hit Breakpoint 2, Protocol_classic::send_ok (this=0x7f542c0508b0, server_status=2,
statement_warn_count=0, affected_rows=0, last_insert_id=0, message=0x7f542c19cfb0 "")
at /data/mysql-8.0.42/sql/protocol_classic.cc:1300
1300 DBUG_TRACE;
Protocol_classic::send_ok函数负责服务端传输OK响应包给客户端。
/**
A default implementation of "OK" packet response to the client.
Currently this implementation is re-used by both network-oriented
protocols -- the binary and text one. They do not differ
in their OK packet format, which allows for a significant simplification
on client side.
*/
bool Protocol_classic::send_ok(uint server_status, uint statement_warn_count,
ulonglong affected_rows,
ulonglong last_insert_id, const char *message) {
DBUG_TRACE;
const bool retval =
net_send_ok(m_thd, server_status, statement_warn_count, affected_rows,
last_insert_id, message, false);
// Reclaim some memory
convert.shrink(m_thd->variables.net_buffer_length);
return retval;
}
对应的执行路径。
(gdb) backtrace
#0 Protocol_classic::send_ok (this=0x7f542c0508b0, server_status=2, statement_warn_count=0, affected_rows=0,
last_insert_id=0, message=0x7f542c19cfb0 "") at /data/mysql-8.0.42/sql/protocol_classic.cc:1300
#1 0x00000000035304c6 in THD::send_statement_status (this=0x7f542c19a5a0) at /data/mysql-8.0.42/sql/sql_class.cc:2927
#2 0x0000000003594e0f in login_connection (thd=0x7f542c19a5a0) at /data/mysql-8.0.42/sql/sql_connect.cc:707
#3 0x0000000003595d29 in thd_prepare_connection (thd=0x7f542c19a5a0) at /data/mysql-8.0.42/sql/sql_connect.cc:893
#4 0x000000000384457a in handle_connection (arg=0xc448c60)
at /data/mysql-8.0.42/sql/conn_handler/connection_handler_per_thread.cc:299
#5 0x00000000058bf53d in pfs_spawn_thread (arg=0xc430ac0) at /data/mysql-8.0.42/storage/perfschema/pfs.cc:3050
#6 0x00007f54cde821ca in start_thread (arg=<optimized out>) at pthread_create.c:479
#7 0x00007f54cc3a18d3 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
继续后续的调试。
(gdb) c
Continuing.
Thread 36 "connection" hit Breakpoint 3, do_command (thd=0x7f542c19a5a0) at /data/mysql-8.0.42/sql/sql_parse.cc:1311
1311 NET *net = nullptr;
(gdb) backtrace
#0 do_command (thd=0x7f542c19a5a0) at /data/mysql-8.0.42/sql/sql_parse.cc:1311
#1 0x0000000003844598 in handle_connection (arg=0xc448c60)
at /data/mysql-8.0.42/sql/conn_handler/connection_handler_per_thread.cc:303
#2 0x00000000058bf53d in pfs_spawn_thread (arg=0xc430ac0) at /data/mysql-8.0.42/storage/perfschema/pfs.cc:3050
#3 0x00007f54cde821ca in start_thread (arg=<optimized out>) at pthread_create.c:479
#4 0x00007f54cc3a18d3 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
(gdb) info local
return_value = false
rc = 739878304
net = 0x7f54000000df
command = COM_SLEEP
com_data = {com_init_db = {db_name = 0x7f54a4165a80 "\260Z\026\244T\177", length = 55460967}, com_refresh = {
options = 128 '\200'}, com_kill = {id = 140001506908800}, com_set_option = {opt_command = 2752928384},
com_stmt_execute = {stmt_id = 140001506908800, open_cursor = 55460967, parameters = 0x8c03f40 <connection_attrib>,
parameter_count = 139999493868308, has_new_types = 176 '\260'}, com_stmt_fetch = {stmt_id = 140001506908800,
num_rows = 55460967}, com_stmt_send_long_data = {stmt_id = 140001506908800, param_number = 55460967,
longdata = 0x8c03f40 <connection_attrib> "", length = 139999493868308}, com_stmt_prepare = {
query = 0x7f54a4165a80 "\260Z\026\244T\177", length = 55460967}, com_stmt_close = {stmt_id = 2752928384},
com_stmt_reset = {stmt_id = 2752928384}, com_query = {query = 0x7f54a4165a80 "\260Z\026\244T\177", length = 55460967,
parameters = 0x8c03f40 <connection_attrib>, parameter_count = 139999493868308}, com_field_list = {
table_name = 0x7f54a4165a80 "\260Z\026\244T\177", table_name_length = 55460967,
query = 0x8c03f40 <connection_attrib> "", query_length = 739887892}}
_db_trace = {m_stack_frame = {func = 0x7f54a4165a60 "\200Z\026\244T\177", func_len = 55462929,
file = 0x500000005 <error: Cannot access memory at address 0x500000005>, level = 739887892, prev = 0x72cd953}}
__PRETTY_FUNCTION__ = "bool do_command(THD*)"
query_start_status = {created_tmp_disk_tables = 140001871885264, created_tmp_tables = 140001871885264,
ha_commit_count = 140001506907072, ha_delete_count = 93223725, ha_read_first_count = 140001506907256,
ha_read_last_count = 140001882016256, ha_read_key_count = 140001506907120, ha_read_next_count = 5954958927198244352,
ha_read_prev_count = 140001506907256, ha_read_rnd_count = 202066864, ha_read_rnd_next_count = 140001506907168,
ha_multi_range_read_init_count = 1, ha_rollback_count = 139999493863680, ha_update_count = 146816832,
ha_write_count = 140001506909248, ha_prepare_count = 63438843, ha_discover_count = 139999492204256,
ha_savepoint_count = 1, ha_savepoint_rollback_count = 140001506907200, ha_external_lock_count = 54875113,
opened_tables = 140001506907256, opened_shares = 140001506907264, table_open_cache_hits = 140001506907760,
table_open_cache_misses = 63428291, table_open_cache_overflows = 140001506907408,
select_full_join_count = 139999493899952, select_full_range_join_count = 8589934592,
select_range_count = 139999493859632, select_range_check_count = 140001506907456, select_scan_count = 1,
long_query_count = 120379725, filesort_merge_passes = 0, filesort_range_count = 120379731, filesort_rows = 2147483649,
filesort_scan_count = 0, com_stmt_prepare = 56813002, com_stmt_reprepare = 0, com_stmt_execute = 0,
com_stmt_send_long_data = 0, com_stmt_fetch = 0, com_stmt_reset = 0, com_stmt_close = 0, bytes_received = 0,
bytes_sent = 0, max_execution_time_exceeded = 0, max_execution_time_set = 0, max_execution_time_set_failed = 0,
--Type <RET> for more, q to quit, c to continue without paging--q
questionQuit
(gdb) info args
thd = 0x7f542c19a5a0
(gdb) print *thd
$25 = {<MDL_context_owner> = {_vptr.MDL_context_owner = 0x86ecb00 <vtable for THD+16>}, <Query_arena> = {
_vptr.Query_arena = 0x86ecb70 <vtable for THD+128>, m_item_list = 0x0, mem_root = 0x7f542c19ced0,
is_repreparing = false, state = Query_arena::STMT_REGULAR_EXECUTION}, <Open_tables_state> = {
m_reprepare_observers = {static Has_trivial_destructor = <optimized out>, static initial_capacity = <optimized out>,
m_psi_key = 0, m_inline_size = 0, {m_ext = {m_array_ptr = 0x0, m_alloced_size = 0, m_alloced_capacity = 0},
m_buff = {0x0, 0x0, 0x0, 0x0}}}, open_tables = 0x0, temporary_tables = 0x0, lock = 0x0, extra_lock = 0x0,
locked_tables_mode = LTM_NONE, state_flags = 0}, m_mem_cnt = {m_enabled = true, m_thd = 0x7f542c19a5a0, m_da = {
m_stacked_da = 0x0, m_condition_root = {static s_dummy_target = 0 '\000', m_current_block = 0x0,
m_current_free_start = 0x8cb2350 <MEM_ROOT::s_dummy_target> "",
m_current_free_end = 0x8cb2350 <MEM_ROOT::s_dummy_target> "", m_block_size = 2048, m_orig_block_size = 2048,
m_max_capacity = 0, m_allocated_size = 0, m_error_for_capacity_exceeded = false,
m_error_handler = 0x34f935d <sql_alloc_error_handler()>, m_psi_key = 0},
m_conditions_list = {<I_P_List_counter> = {m_counter = 0}, <I_P_List_fast_push_back<Sql_condition>> = {
m_last = 0x7f542c19a690}, m_first = 0x0}, m_preexisting_sql_conditions = {<base_list> = {
first = 0x8c08d70 <end_of_list>, last = 0x7f542c19a698, elements = 0}, <No data fields>}, m_is_sent = false,
m_can_overwrite_status = false, m_allow_unlimited_conditions = false, m_status = Diagnostics_area::DA_EMPTY,
m_message_text = "\000d=1;row_type=2;stats_auto_recalc=0;stats_persistent=0;stats_sample_pages=0;\000\000\000\000", '\337' <repeats 16 times>, '\000' <repeats 415 times>, m_message_text_length = 0,
m_returned_sqlstate = "\000\000\000\000\000", m_mysql_errno = 0, m_affected_rows = 0, m_last_insert_id = 0,
m_last_statement_cond_count = 0, m_current_statement_cond_count = 0, m_current_statement_cond_count_by_qb = {0, 0,
0}, m_current_row_for_condition = 1, m_saved_error_count = 0, m_saved_warn_count = 0}, mem_counter = 8240,
max_conn_mem = 8240, glob_mem_counter = 0, curr_mode = 0, orig_mode = 7, is_connection_stage = true}, mdl_context = {
m_wait = {m_LOCK_wait_status = {m_mutex = {m_u = {m_native = {__data = {__lock = 739830096, __count = 32596,
__owner = 0, __nusers = 0, __kind = 0, __spins = 0, __elision = 0, __list = {__prev = 0x0,
__next = 0x0}}, __size = "P\351\030,T\177", '\000' <repeats 33 times>, __align = 139999493810512},
m_safe_ptr = 0x7f542c18e950}}, m_psi = 0xc21cfa0}, m_COND_wait_status = {m_cond = {__data = {{__wseq = 0,
__wseq32 = {__low = 0, __high = 0}}, {__g1_start = 0, __g1_start32 = {__low = 0, __high = 0}},
__glibc_unused___g_refs = {0, 0}, __g_size = {0, 0}, __g1_orig_size = 0, __wrefs = 0, __g_signals = {0, 0}},
__size = '\000' <repeats 47 times>, __align = 0}, m_psi = 0xc010c58}, m_wait_status = MDL_wait::WS_EMPTY},
m_ticket_store = {m_durations = {{
m_ticket_list = {<I_P_List_null_counter> = {<No data fields>}, <I_P_List_no_push_back<MDL_ticket>> = {<No data fields>}, m_first = 0x0}, m_mat_front = 0x0}, {
m_ticket_list = {<I_P_List_null_counter> = {<No data fields>}, <I_P_List_no_push_back<MDL_ticket>> = {<No data f--Type <RET> for more, q to quit, c to continue without paging--q
Quit
do_command函数会从连接中读取一个命令并执行。
/**
Read one command from connection and execute it (query or simple command).
This function is called in loop from thread function.
For profiling to work, it must never be called recursively.
@retval
0 success
@retval
1 request of thread shutdown (see dispatch_command() description)
*/
bool do_command(THD *thd) {
bool return_value;
int rc;
NET *net = nullptr;
enum enum_server_command command = COM_SLEEP;
COM_DATA com_data;
DBUG_TRACE;
assert(thd->is_classic_protocol());
/*
indicator of uninitialized lex => normal flow of errors handling
(see my_message_sql)
*/
thd->lex->set_current_query_block(nullptr);
..
打印command变量,刚进入函数,里面的值是COM_SLEEP。
(gdb) print command
$26 = COM_SLEEP
继续调试后续的代码。
(gdb) next
1312 enum enum_server_command command = COM_SLEEP;
(gdb) n
1314 DBUG_TRACE;
(gdb) n
1315 assert(thd->is_classic_protocol());
(gdb) print command
$30 = COM_SLEEP
(gdb) n
1321 thd->lex->set_current_query_block(nullptr);
(gdb) print command
$31 = COM_SLEEP
(gdb) n
1329 thd->clear_error(); // Clear error message
(gdb) n
1330 thd->get_stmt_da()->reset_diagnostics_area();
(gdb) print command
$32 = COM_SLEEP
(gdb) n
1338 net = thd->get_protocol_classic()->get_net();
(gdb) print command
$33 = COM_SLEEP
(gdb) n
1339 my_net_set_read_timeout(net, thd->variables.net_wait_timeout);
(gdb) print command
$34 = COM_SLEEP
(gdb) n
1340 net_new_transaction(net);
(gdb) print command
$35 = COM_SLEEP
(gdb) n
1356 DEBUG_SYNC(thd, "before_do_command_net_read");
(gdb) n
1360 thd->clear_copy_status_var();
(gdb) n
1361 if (opt_log_slow_extra) {
(gdb) print command
$36 = COM_SLEEP
(gdb) n
1365 rc = thd->m_mem_cnt.reset();
(gdb) print command
$37 = COM_SLEEP
(gdb) n
1366 if (rc)
(gdb) n
1380 thd->m_server_idle = true;
(gdb) n
1381 rc = thd->get_protocol()->get_command(&com_data, &command);
(gdb) n
Thread 36 "connection" hit Breakpoint 4, Protocol_classic::get_command (this=0x7f542c0508b0, com_data=0x7f54a4165a60,
cmd=0x7f54a4165a8c) at /data/mysql-8.0.42/sql/protocol_classic.cc:2993
2993 if (int rc = read_packet()) return rc;
(gdb) print command
No symbol "command" in current context.
(gdb) c
Continuing.
Thread 36 "connection" hit Breakpoint 1, Protocol_classic::read_packet (this=0x7f542c0508b0)
at /data/mysql-8.0.42/sql/protocol_classic.cc:1410
1410 input_packet_length = my_net_read(&m_thd->net);
(gdb) c
Continuing.
Thread 36 "connection" hit Breakpoint 10, my_net_read (net=0x7f542c19c398)
at /data/mysql-8.0.42/sql-common/net_serv.cc:2268
2268 if (!vio_is_blocking(net->vio)) vio_set_blocking_flag(net->vio, true);
Protocol_classic::get_command函数会解析包中的命令。
int Protocol_classic::get_command(COM_DATA *com_data,
enum_server_command *cmd) {
// read packet from the network
if (int rc = read_packet()) return rc;
/*
'input_packet_length' contains length of data, as it was stored in packet
header. In case of malformed header, my_net_read returns zero.
If input_packet_length is not zero, my_net_read ensures that the returned
number of bytes was actually read from network.
There is also an extra safety measure in my_net_read:
it sets packet[input_packet_length]= 0, but only for non-zero packets.
*/
if (input_packet_length == 0) /* safety */
{
/* Initialize with COM_SLEEP packet */
input_raw_packet[0] = (uchar)COM_SLEEP;
input_packet_length = 1;
}
/* Do not rely on my_net_read, extra safety against programming errors. */
input_raw_packet[input_packet_length] = '\0'; /* safety */
*cmd = (enum enum_server_command)(uchar)input_raw_packet[0];
if (*cmd >= COM_END) *cmd = COM_END; // Wrong command
assert(input_packet_length);
// Skip 'command'
input_packet_length--;
input_raw_packet++;
return parse_packet(com_data, *cmd);
}
接着调试后续的代码。
(gdb) c
Continuing.
Thread 36 "connection" hit Breakpoint 5, dispatch_command (thd=0x7f542c19a5a0, com_data=0x7f54a4165a60,
command=COM_QUERY) at /data/mysql-8.0.42/sql/sql_parse.cc:1690
1690 assert(thd->lex->m_IS_table_stats.is_valid() == false);
(gdb) info local
__PRETTY_FUNCTION__ = "bool dispatch_command(THD*, const COM_DATA*, enum_server_command)"
tabstat_grd = {m_is_released = 114, m_cleanup_lambda = {__thd = @0x160000ffff}}
error = false
thd_manager = 0x0
_db_trace = {m_stack_frame = {func = 0x4018 <error: Cannot access memory at address 0x4018>, func_len = -868212155,
file = 0x0, level = 0, prev = 0x7f54a4165170}}
clone_cmd = 0x65ade7c
__FUNCTION__ = "dispatch_command"
__func__ = "dispatch_command"
cn = "my_net_set_read_timeout"
kPreallocSz = 0
(gdb) info args
thd = 0x7f542c19a5a0
com_data = 0x7f54a4165a60
command = COM_QUERY
(gdb) bt
#0 dispatch_command (thd=0x7f542c19a5a0, com_data=0x7f54a4165a60, command=COM_QUERY)
at /data/mysql-8.0.42/sql/sql_parse.cc:1690
#1 0x000000000361c5ca in do_command (thd=0x7f542c19a5a0) at /data/mysql-8.0.42/sql/sql_parse.cc:1440
#2 0x0000000003844598 in handle_connection (arg=0xc448c60)
at /data/mysql-8.0.42/sql/conn_handler/connection_handler_per_thread.cc:303
#3 0x00000000058bf53d in pfs_spawn_thread (arg=0xc430ac0) at /data/mysql-8.0.42/storage/perfschema/pfs.cc:3050
#4 0x00007f54cde821ca in start_thread (arg=<optimized out>) at pthread_create.c:479
#5 0x00007f54cc3a18d3 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
dispatch_command函数会执行连接中发送过来的命令。
/**
Perform one connection-level (COM_XXXX) command.
@param thd connection handle
@param command type of command to perform
@param com_data com_data union to store the generated command
@todo
set thd->lex->sql_command to SQLCOM_END here.
@todo
The following has to be changed to an 8 byte integer
@retval
0 ok
@retval
1 request of thread shutdown, i. e. if command is
COM_QUIT
*/
bool dispatch_command(THD *thd, const COM_DATA *com_data,
enum enum_server_command command) {
assert(thd->lex->m_IS_table_stats.is_valid() == false);
assert(thd->lex->m_IS_tablespace_stats.is_valid() == false);
..
这个时候command变量的值是COM_QUERY,去处理一个查询请求。
(gdb) print command
$38 = COM_QUERY
继续后续的调试。
(gdb) n
1691 assert(thd->lex->m_IS_tablespace_stats.is_valid() == false);
(gdb) n
1696 });
(gdb) n
1698 bool error = false;
(gdb) n
1699 Global_THD_manager *thd_manager = Global_THD_manager::get_instance();
(gdb) n
1700 DBUG_TRACE;
(gdb) n
1701 DBUG_PRINT("info", ("command: %d", command));
(gdb) n
1703 Sql_cmd_clone *clone_cmd = nullptr;
(gdb) n
1707 thd->profiling->start_new_query();
(gdb) n
1711 thd->m_statement_psi = MYSQL_REFINE_STATEMENT(
(gdb) n
1714 thd->set_command(command);
(gdb) n
1719 thd->enable_slow_log = true;
(gdb) n
1720 thd->lex->sql_command = SQLCOM_END; /* to avoid confusing VIEW detectors */
(gdb) n
1730 if (thd->killed == THD::KILL_QUERY) thd->killed = THD::NOT_KILLED;
(gdb) n
1731 thd->set_time();
(gdb) n
1732 if (is_time_t_valid_for_timestamp(thd->query_start_in_secs()) == false) {
(gdb) n
1768 thd->set_query_id(next_query_id());
(gdb) n
1769 thd->reset_rewritten_query();
(gdb) n
1770 thd_manager->inc_thread_running();
(gdb) n
1772 if (!(server_command_flags[command] & CF_SKIP_QUESTIONS))
(gdb) n
1773 thd->status_var.questions++;
(gdb) n
1779 thd->server_status &= ~SERVER_STATUS_CLEAR_SET;
(gdb) n
1781 if (thd->get_protocol()->type() == Protocol::PROTOCOL_PLUGIN &&
(gdb) n
1800 if (unlikely(thd->security_context()->password_expired() &&
(gdb)
1803 command != COM_QUIT && command != COM_STMT_PREPARE &&
(gdb) n
1800 if (unlikely(thd->security_context()->password_expired() &&
(gdb)
1810 Command_names::str_global(command).c_str())) {
(gdb)
1809 if (mysql_audit_notify(thd, AUDIT_EVENT(MYSQL_AUDIT_COMMAND_START), command,
(gdb)
1814 switch (command) {
(gdb) n
2012 assert(thd->m_digest == nullptr);
(gdb) n
2013 thd->m_digest = &thd->m_digest_state;
(gdb) n
2014 thd->m_digest->reset(thd->m_token_array, max_digest_length);
(gdb) n
2017 com_data->com_query.length))
(gdb) n
2016 if (alloc_query(thd, com_data->com_query.query,
(gdb) n
2020 const char *packet_end = thd->query().str + thd->query().length;
(gdb) n
2022 if (opt_general_log_raw)
(gdb) n
2026 DBUG_PRINT("query", ("%-.4096s", thd->query().str));
(gdb) n
2029 thd->profiling->set_query_source(thd->query().str, thd->query().length);
(gdb) n
2032 const LEX_CSTRING orig_query = thd->query();
(gdb) n
2034 Parser_state parser_state;
(gdb) n
2035 if (parser_state.init(thd, thd->query().str, thd->query().length)) break;
(gdb) c
Continuing.
Thread 36 "connection" hit Breakpoint 6, Protocol_classic::start_result_metadata (this=0x7f542c0508b0, num_cols_arg=1,
flags=5, cs=0x8a09400 <my_charset_utf8mb4_0900_ai_ci>) at /data/mysql-8.0.42/sql/protocol_classic.cc:3081
3081 DBUG_TRACE;
(gdb) info args
this = 0x7f542c0508b0
num_cols_arg = 1
flags = 5
cs = 0x8a09400 <my_charset_utf8mb4_0900_ai_ci>
(gdb) print *cs
$39 = {number = 255, primary_number = 0, binary_number = 0, state = 17377, csname = 0x785420e "utf8mb4",
m_coll_name = 0x78548a0 "utf8mb4_0900_ai_ci", comment = 0x7854051 "UTF-8 Unicode", tailoring = 0x0, coll_param = 0x0,
ctype = 0x7853f20 <ctype_utf8> "", to_lower = 0x0, to_upper = 0x0, sort_order = 0x0, uca = 0x89f9600 <my_uca_v900>,
tab_to_uni = 0x0, tab_from_uni = 0x0, caseinfo = 0x89f95e0 <my_unicase_unicode900>, state_maps = 0xc0a0dd0,
ident_map = 0xc0a0fd0 "", strxfrm_multiply = 0, caseup_multiply = 1 '\001', casedn_multiply = 1 '\001', mbminlen = 1,
mbmaxlen = 4, mbmaxlenlen = 1, min_sort_char = 9, max_sort_char = 1114111, pad_char = 32 ' ',
escape_with_backslash_is_dangerous = false, levels_for_compare = 1 '\001',
cset = 0x8a26a60 <my_charset_utf8mb4_handler>, coll = 0x8a03da0 <my_collation_uca_900_handler>, pad_attribute = NO_PAD}
Protocol_classic::start_result_metadata会生成查询结果的元数据。
bool Protocol_classic::start_result_metadata(uint num_cols_arg, uint flags,
const CHARSET_INFO *cs) {
DBUG_TRACE;
DBUG_PRINT("info", ("num_cols %u, flags %u", num_cols_arg, flags));
uint num_cols = num_cols_arg;
result_cs = cs;
send_metadata = true;
field_count = num_cols;
sending_flags = flags;
..
/*
We don't send number of column for PS, as it's sent in a preceding packet.
*/
if (flags & Protocol::SEND_NUM_ROWS) {
uchar tmp[sizeof(ulonglong) + 1];
uchar *pos = net_store_length((uchar *)&tmp, num_cols);
if (has_client_capability(CLIENT_OPTIONAL_RESULTSET_METADATA)) {
/* Store resultset metadata flag. */
*pos = static_cast<uchar>(m_thd->variables.resultset_metadata);
pos++;
}
my_net_write(&m_thd->net, (uchar *)&tmp, (size_t)(pos - (uchar *)&tmp));
}
..
/*
field_types will be filled only if we send metadata.
Set it to NULL if we skip resultset metadata to avoid
::storeXXX() method's asserts failures.
*/
if (m_thd->variables.resultset_metadata == RESULTSET_METADATA_FULL)
field_types =
(enum_field_types *)m_thd->alloc(sizeof(field_types) * num_cols);
else
field_types = nullptr;
..
查看执行路径。
语句在解析、查询后,最后会进行查询结果的处理。
(gdb) backtrace
#0 Protocol_classic::start_result_metadata (this=0x7f542c0508b0, num_cols_arg=1, flags=5,
cs=0x8a09400 <my_charset_utf8mb4_0900_ai_ci>) at /data/mysql-8.0.42/sql/protocol_classic.cc:3081
#1 0x000000000352fd4f in THD::send_result_metadata (this=0x7f542c19a5a0, list=..., flags=5)
at /data/mysql-8.0.42/sql/sql_class.cc:2851
#2 0x0000000003ce7929 in Query_result_send::send_result_set_metadata (this=0x7f542c1b0070, thd=0x7f542c19a5a0,
list=..., flags=5) at /data/mysql-8.0.42/sql/query_result.cc:71
#3 0x000000000375ef48 in Query_expression::ExecuteIteratorQuery (this=0x7f542c0d48c0, thd=0x7f542c19a5a0)
at /data/mysql-8.0.42/sql/sql_union.cc:1703
#4 0x000000000375f610 in Query_expression::execute (this=0x7f542c0d48c0, thd=0x7f542c19a5a0)
at /data/mysql-8.0.42/sql/sql_union.cc:1836
#5 0x00000000036ac5ec in Sql_cmd_dml::execute_inner (this=0x7f542c1b0038, thd=0x7f542c19a5a0)
at /data/mysql-8.0.42/sql/sql_select.cc:1014
#6 0x00000000036aba23 in Sql_cmd_dml::execute (this=0x7f542c1b0038, thd=0x7f542c19a5a0)
at /data/mysql-8.0.42/sql/sql_select.cc:785
#7 0x00000000036266d2 in mysql_execute_command (thd=0x7f542c19a5a0, first_level=true)
at /data/mysql-8.0.42/sql/sql_parse.cc:4724
#8 0x0000000003628aae in dispatch_sql_command (thd=0x7f542c19a5a0, parser_state=0x7f54a4164970)
at /data/mysql-8.0.42/sql/sql_parse.cc:5385
#9 0x000000000361e683 in dispatch_command (thd=0x7f542c19a5a0, com_data=0x7f54a4165a60, command=COM_QUERY)
at /data/mysql-8.0.42/sql/sql_parse.cc:2055
#10 0x000000000361c5ca in do_command (thd=0x7f542c19a5a0) at /data/mysql-8.0.42/sql/sql_parse.cc:1440
#11 0x0000000003844598 in handle_connection (arg=0xc448c60)
at /data/mysql-8.0.42/sql/conn_handler/connection_handler_per_thread.cc:303
#12 0x00000000058bf53d in pfs_spawn_thread (arg=0xc430ac0) at /data/mysql-8.0.42/storage/perfschema/pfs.cc:3050
#13 0x00007f54cde821ca in start_thread (arg=<optimized out>) at pthread_create.c:479
#14 0x00007f54cc3a18d3 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
接着调试后续的代码。
(gdb) c
Continuing.
Thread 36 "connection" hit Breakpoint 7, Protocol_classic::store_string (this=0x7f542c0508b0, from=0x6774d37 "def",
length=3, fromcs=0x8a26400 <my_charset_utf8mb3_general_ci>) at /data/mysql-8.0.42/sql/protocol_classic.cc:3425
3425 assert(send_metadata || field_types == nullptr ||
(gdb) backtrace
#0 Protocol_classic::store_string (this=0x7f542c0508b0, from=0x6774d37 "def", length=3,
fromcs=0x8a26400 <my_charset_utf8mb3_general_ci>) at /data/mysql-8.0.42/sql/protocol_classic.cc:3425
#1 0x0000000003ce47d3 in Protocol_classic::send_field_metadata (this=0x7f542c0508b0, field=0x7f54a4162b80,
item_charset=0x8a26400 <my_charset_utf8mb3_general_ci>) at /data/mysql-8.0.42/sql/protocol_classic.cc:3282
#2 0x000000000352fe82 in THD::send_result_metadata (this=0x7f542c19a5a0, list=..., flags=5)
at /data/mysql-8.0.42/sql/sql_class.cc:2861
#3 0x0000000003ce7929 in Query_result_send::send_result_set_metadata (this=0x7f542c1b0070, thd=0x7f542c19a5a0,
list=..., flags=5) at /data/mysql-8.0.42/sql/query_result.cc:71
#4 0x000000000375ef48 in Query_expression::ExecuteIteratorQuery (this=0x7f542c0d48c0, thd=0x7f542c19a5a0)
at /data/mysql-8.0.42/sql/sql_union.cc:1703
#5 0x000000000375f610 in Query_expression::execute (this=0x7f542c0d48c0, thd=0x7f542c19a5a0)
at /data/mysql-8.0.42/sql/sql_union.cc:1836
#6 0x00000000036ac5ec in Sql_cmd_dml::execute_inner (this=0x7f542c1b0038, thd=0x7f542c19a5a0)
at /data/mysql-8.0.42/sql/sql_select.cc:1014
#7 0x00000000036aba23 in Sql_cmd_dml::execute (this=0x7f542c1b0038, thd=0x7f542c19a5a0)
at /data/mysql-8.0.42/sql/sql_select.cc:785
#8 0x00000000036266d2 in mysql_execute_command (thd=0x7f542c19a5a0, first_level=true)
at /data/mysql-8.0.42/sql/sql_parse.cc:4724
#9 0x0000000003628aae in dispatch_sql_command (thd=0x7f542c19a5a0, parser_state=0x7f54a4164970)
at /data/mysql-8.0.42/sql/sql_parse.cc:5385
#10 0x000000000361e683 in dispatch_command (thd=0x7f542c19a5a0, com_data=0x7f54a4165a60, command=COM_QUERY)
at /data/mysql-8.0.42/sql/sql_parse.cc:2055
#11 0x000000000361c5ca in do_command (thd=0x7f542c19a5a0) at /data/mysql-8.0.42/sql/sql_parse.cc:1440
#12 0x0000000003844598 in handle_connection (arg=0xc448c60)
at /data/mysql-8.0.42/sql/conn_handler/connection_handler_per_thread.cc:303
#13 0x00000000058bf53d in pfs_spawn_thread (arg=0xc430ac0) at /data/mysql-8.0.42/storage/perfschema/pfs.cc:3050
#14 0x00007f54cde821ca in start_thread (arg=<optimized out>) at pthread_create.c:479
#15 0x00007f54cc3a18d3 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
(gdb) info local
__PRETTY_FUNCTION__ = "virtual bool Protocol_classic::store_string(const char*, size_t, const CHARSET_INFO*)"
(gdb) info args
this = 0x7f542c0508b0
from = 0x6774d37 "def"
length = 3
fromcs = 0x8a26400 <my_charset_utf8mb3_general_ci>
(gdb) print *from
$40 = 100 'd'
Protocol_classic::store_string这个函数主要用于将字符串数据存储到网络协议包中,以便发送给客户端。
bool Protocol_classic::store_string(const char *from, size_t length,
const CHARSET_INFO *fromcs) {
// field_types check is needed because of the embedded protocol
assert(send_metadata || field_types == nullptr ||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
field_types[field_pos] == MYSQL_TYPE_BIT ||
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
field_types[field_pos] == MYSQL_TYPE_NEWDATE ||
field_types[field_pos] == MYSQL_TYPE_JSON ||
(field_types[field_pos] >= MYSQL_TYPE_ENUM &&
field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
field_pos++;
// result_cs is nullptr when client issues SET character_set_results=NULL
if (result_cs != nullptr && !my_charset_same(fromcs, result_cs) &&
fromcs != &my_charset_bin && result_cs != &my_charset_bin) {
// Store with conversion.
return net_store_data_with_conversion(pointer_cast<const uchar *>(from),
length, fromcs, result_cs);
}
// Store without conversion.
return net_store_data(pointer_cast<const uchar *>(from), length, packet);
}
继续后续的调试。
(gdb) c
Continuing.
Thread 36 "connection" hit Breakpoint 7, Protocol_classic::store_string (this=0x7f542c0508b0, from=0x66e83d0 "",
length=0, fromcs=0x8a26400 <my_charset_utf8mb3_general_ci>) at /data/mysql-8.0.42/sql/protocol_classic.cc:3425
3425 assert(send_metadata || field_types == nullptr ||
(gdb) print from
$41 = 0x66e83d0 ""
(gdb) print *from
$42 = 0 '\000'
(gdb) c
Continuing.
Thread 36 "connection" hit Breakpoint 7, Protocol_classic::store_string (this=0x7f542c0508b0, from=0x66e83d0 "",
length=0, fromcs=0x8a26400 <my_charset_utf8mb3_general_ci>) at /data/mysql-8.0.42/sql/protocol_classic.cc:3425
3425 assert(send_metadata || field_types == nullptr ||
(gdb) print *from
$43 = 0 '\000'
(gdb) c
Continuing.
Thread 36 "connection" hit Breakpoint 7, Protocol_classic::store_string (this=0x7f542c0508b0, from=0x66e83d0 "",
length=0, fromcs=0x8a26400 <my_charset_utf8mb3_general_ci>) at /data/mysql-8.0.42/sql/protocol_classic.cc:3425
3425 assert(send_metadata || field_types == nullptr ||
(gdb) c
Continuing.
Thread 36 "connection" hit Breakpoint 7, Protocol_classic::store_string (this=0x7f542c0508b0,
from=0x7f542c0d5c70 "@@version_comment", length=17, fromcs=0x8a26400 <my_charset_utf8mb3_general_ci>)
at /data/mysql-8.0.42/sql/protocol_classic.cc:3425
3425 assert(send_metadata || field_types == nullptr ||
(gdb) c
Continuing.
Thread 36 "connection" hit Breakpoint 7, Protocol_classic::store_string (this=0x7f542c0508b0, from=0x66e83d0 "",
length=0, fromcs=0x8a26400 <my_charset_utf8mb3_general_ci>) at /data/mysql-8.0.42/sql/protocol_classic.cc:3425
3425 assert(send_metadata || field_types == nullptr ||
(gdb) c
Continuing.
Thread 36 "connection" hit Breakpoint 8, THD::send_result_set_row (this=0x7f542c19a5a0, row_items=...)
at /data/mysql-8.0.42/sql/sql_class.cc:2887
2887 String str_buffer(buffer, sizeof(buffer), &my_charset_bin);
(gdb) info local
buffer = "\340f\000,T\177\000\000\000\000\000\000\000\000\000\000P,\026\244T\177\000\000 \000\000\000\000\000\000\000\000\224\240\b", '\000' <repeats 12 times>, "P,\026\244T\177\000\000\263\372\310\004\000\000\000\000P0\026\244T\177\000\000\300\026\313\b\000\000\000\000p,\026\244T\177\000\000\253\374\310\004\000\000\000\000\270\272\000,T\177\000\000\340f\000,T\177\000\000\240.\026\244T\177\000\000/(\311\004\000\000\000\000\000/\026\244T\177\000\000\001\000\000\000\000\000\000\000\260,\026\244T\177\000\000\263\372\310\004\000\000\000\000\300,\026\244T\177\000\000\300\026\313\b\000\000\000\000\320,\026\244T\177\000\000\253\374\310\004\000\000\000\000\270\272\000,T\177\000\000"...
str_buffer = {m_ptr = 0x88b7280 <my_charset_bin> "?", m_length = 766, m_charset = 0x7f54a4162c10,
m_alloced_length = 80280243, m_is_alloced = false}
_db_trace = {m_stack_frame = {func = 0x21 <error: Cannot access memory at address 0x21>, func_len = 31,
file = 0x7f54a4162b00 "@+\026\244T\177", level = 739068392, prev = 0x7f54a4162bf0}}
__PRETTY_FUNCTION__ = "bool THD::send_result_set_row(const mem_root_deque<Item*>&)"
(gdb) info args
this = 0x7f542c19a5a0
row_items = @0x7f542c0d49e8: {static block_elements = <optimized out>, m_blocks = 0x7f542c0d5ca8, m_begin_idx = 64,
m_end_idx = 65, m_capacity = 128, m_root = 0x7f542c19ced0, m_generation = 2}
(gdb) print row_items
$44 = (const mem_root_deque<Item*> &) @0x7f542c0d49e8: {static block_elements = <optimized out>,
m_blocks = 0x7f542c0d5ca8, m_begin_idx = 64, m_end_idx = 65, m_capacity = 128, m_root = 0x7f542c19ced0,
m_generation = 2}
(gdb) print row_items->m_root
$45 = (MEM_ROOT *) 0x7f542c19ced0
(gdb) print *row_items->m_root
$46 = {static s_dummy_target = 0 '\000', m_current_block = 0x7f542c1aeeb0,
m_current_free_start = 0x7f542c1b0aa8 '\217' <repeats 200 times>...,
m_current_free_end = 0x7f542c1b0ec0 "\217\217\217\217\217\217\217\217\361\037", m_block_size = 12288,
m_orig_block_size = 8192, m_max_capacity = 0, m_allocated_size = 16384, m_error_for_capacity_exceeded = false,
m_error_handler = 0x34f935d <sql_alloc_error_handler()>, m_psi_key = 9}
THD::send_result_set_row负责将查询结果的一行数据发送给客户端。
bool THD::send_result_set_row(const mem_root_deque<Item *> &row_items) {
char buffer[MAX_FIELD_WIDTH];
String str_buffer(buffer, sizeof(buffer), &my_charset_bin);
DBUG_TRACE;
DBUG_EXECUTE_IF("assert_only_current_thd_protocol_access",
{ assert(current_thd == this); });
for (Item *item : VisibleFields(row_items)) {
if (item->send(m_protocol, &str_buffer) || is_error()) return true;
/*
Reset str_buffer to its original state, as it may have been altered in
Item::send().
*/
str_buffer.set(buffer, sizeof(buffer), &my_charset_bin);
}
return false;
}
继续调试后续的代码。
(gdb) c
Continuing.
Thread 36 "connection" hit Breakpoint 9, Item::send (this=0x7f542c0d59a8, protocol=0x7f542c0508b0, buffer=0x7f54a4162be0)
at /data/mysql-8.0.42/sql/item.cc:7350
7350 switch (data_type()) {
(gdb) info local
__PRETTY_FUNCTION__ = "virtual bool Item::send(Protocol*, String*)"
(gdb) info args
this = 0x7f542c0d59a8
protocol = 0x7f542c0508b0
buffer = 0x7f54a4162be0
(gdb) print *protocol
$47 = {_vptr.Protocol = 0x87d3238 <vtable for Protocol_text+16>, m_previous_protocol = 0x0}
(gdb) print *buffer
$48 = {m_ptr = 0x7f54a4162c00 "\340f", m_length = 766, m_charset = 0x88b7280 <my_charset_bin>, m_alloced_length = 766,
m_is_alloced = false}
(gdb) backtrace
#0 Item::send (this=0x7f542c0d59a8, protocol=0x7f542c0508b0, buffer=0x7f54a4162be0)
at /data/mysql-8.0.42/sql/item.cc:7350
#1 0x0000000003530136 in THD::send_result_set_row (this=0x7f542c19a5a0, row_items=...)
at /data/mysql-8.0.42/sql/sql_class.cc:2894
#2 0x0000000003ce7a1e in Query_result_send::send_data (this=0x7f542c1b0070, thd=0x7f542c19a5a0, items=...)
at /data/mysql-8.0.42/sql/query_result.cc:101
#3 0x000000000375f3c2 in Query_expression::ExecuteIteratorQuery (this=0x7f542c0d48c0, thd=0x7f542c19a5a0)
at /data/mysql-8.0.42/sql/sql_union.cc:1798
#4 0x000000000375f610 in Query_expression::execute (this=0x7f542c0d48c0, thd=0x7f542c19a5a0)
at /data/mysql-8.0.42/sql/sql_union.cc:1836
#5 0x00000000036ac5ec in Sql_cmd_dml::execute_inner (this=0x7f542c1b0038, thd=0x7f542c19a5a0)
at /data/mysql-8.0.42/sql/sql_select.cc:1014
#6 0x00000000036aba23 in Sql_cmd_dml::execute (this=0x7f542c1b0038, thd=0x7f542c19a5a0)
at /data/mysql-8.0.42/sql/sql_select.cc:785
#7 0x00000000036266d2 in mysql_execute_command (thd=0x7f542c19a5a0, first_level=true)
at /data/mysql-8.0.42/sql/sql_parse.cc:4724
#8 0x0000000003628aae in dispatch_sql_command (thd=0x7f542c19a5a0, parser_state=0x7f54a4164970)
at /data/mysql-8.0.42/sql/sql_parse.cc:5385
#9 0x000000000361e683 in dispatch_command (thd=0x7f542c19a5a0, com_data=0x7f54a4165a60, command=COM_QUERY)
at /data/mysql-8.0.42/sql/sql_parse.cc:2055
#10 0x000000000361c5ca in do_command (thd=0x7f542c19a5a0) at /data/mysql-8.0.42/sql/sql_parse.cc:1440
#11 0x0000000003844598 in handle_connection (arg=0xc448c60)
at /data/mysql-8.0.42/sql/conn_handler/connection_handler_per_thread.cc:303
#12 0x00000000058bf53d in pfs_spawn_thread (arg=0xc430ac0) at /data/mysql-8.0.42/storage/perfschema/pfs.cc:3050
#13 0x00007f54cde821ca in start_thread (arg=<optimized out>) at pthread_create.c:479
#14 0x00007f54cc3a18d3 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Item::send负责将 Item 对象的数据发送到客户端。
/**
This is only called from items that is not of type item_field.
*/
bool Item::send(Protocol *protocol, String *buffer) {
switch (data_type()) {
default:
case MYSQL_TYPE_NULL:
case MYSQL_TYPE_BOOL:
case MYSQL_TYPE_INVALID:
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET:
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_GEOMETRY:
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_BIT:
case MYSQL_TYPE_NEWDECIMAL:
case MYSQL_TYPE_JSON: {
const String *res = val_str(buffer);
assert(null_value == (res == nullptr));
if (res != nullptr)
return protocol->store_string(res->ptr(), res->length(),
res->charset());
break;
}
..
Item::send函数会返回protocol->store_string函数。
(gdb) n
7369 const String *res = val_str(buffer);
(gdb) n
7370 assert(null_value == (res == nullptr));
(gdb) n
7371 if (res != nullptr)
(gdb) n
7372 return protocol->store_string(res->ptr(), res->length(),
(gdb) n
Thread 36 "connection" hit Breakpoint 7, Protocol_classic::store_string (this=0x7f542c0508b0,
from=0x7f542c1a3e70 "MySQL 8.0.42 test environment", length=29, fromcs=0x8a26400 <my_charset_utf8mb3_general_ci>)
at /data/mysql-8.0.42/sql/protocol_classic.cc:3425
3425 assert(send_metadata || field_types == nullptr ||
1176

被折叠的 条评论
为什么被折叠?



