连接处理
连接处理
宏观的来看连接处理只做两件事 1、接收连接请求并把它包装成 Channel_info 对象 2、创建新线程去执行 handle_connection 函数。
// sql/sql/conn_handler/connection_acceptor.h
// 事件循环
void connection_event_loop() {
Connection_handler_manager *mgr =
Connection_handler_manager::get_instance();
// 无限循环下去
while (!connection_events_loop_aborted()) {
// 只要接收到连接就给到 mgr 来处理
Channel_info *channel_info = m_listener->listen_for_connection_event();
if (channel_info != nullptr) mgr->process_new_connection(channel_info);
}
}
// 单个连接的处理
void Connection_handler_manager::process_new_connection(
Channel_info *channel_info) {
if (connection_events_loop_aborted() ||
!check_and_incr_conn_count(channel_info->is_admin_connection())) {
channel_info->send_error_and_close_channel(ER_CON_COUNT_ERROR, 0, true);
delete channel_info;
return;
}
// 事实上 add_connection 里面会负责为新的客户端连接创建对应的线程
//
if (m_connection_handler->add_connection(channel_info)) {
inc_aborted_connects();
delete channel_info;
}
}
// 创建一个线程让它去执行 handle_connection 函数, 函数的参数是 channel_info 对象(连接对象)
bool Per_thread_connection_handler::add_connection(Channel_info *channel_info) {
// ...
error =
mysql_thread_create(key_thread_one_connection, &id, &connection_attrib,
handle_connection, (void *)channel_info);
// ...
}
// 下面是一些于线程相关的技术细节了
// linux 平动上的话,最终用的是 pthread_create 来创建线程的
#define mysql_thread_create(K, P1, P2, P3, P4) \
inline_mysql_thread_create(K, 0, P1, P2, P3, P4)
static inline int inline_mysql_thread_create(
PSI_thread_key key [[maybe_unused]],
unsigned int sequence_number [[maybe_unused]], my_thread_handle *thread,
const my_thread_attr_t *attr, my_start_routine start_routine, void *arg)
{
// ...
result = my_thread_create(thread, attr, start_routine, arg);
return result;
}
int my_thread_create(my_thread_handle *thread, const my_thread_attr_t *attr,
my_start_routine func, void *arg) {
// ...
return pthread_create(&thread->thread, attr, func, arg);
// ...
}
整体上看堆栈
从收到连接到创建工作线程,看堆栈是这样的。
(gdb) bt
0 my_thread_create (thread=0x7ffd9bd569f8, attr=0x8d2cda0 <connection_attrib>, func=0x58b3479 <pfs_spawn_thread(void*)>, arg=0xbed7ca0)
at /data/repos/mysql-8.4.0/mysys/my_thread.cc:81
1 0x00000000058b3723 in pfs_spawn_thread_vc (key=5, seqnum=0, thread=0x7ffd9bd569f8, attr=0x8d2cda0 <connection_attrib>,
start_routine=0x37d9d2a <handle_connection(void*)>, arg=0xbd10b20) at /data/repos/mysql-8.4.0/storage/perfschema/pfs.cc:3097
2 0x00000000037d972a in inline_mysql_thread_create (key=5, sequence_number=0, thread=0x7ffd9bd569f8, attr=0x8d2cda0 <connection_attrib>,
start_routine=0x37d9d2a <handle_connection(void*)>, arg=0xbd10b20) at /data/repos/mysql-8.4.0/include/mysql/psi/mysql_thread.h:140
3 0x00000000037da364 in Per_thread_connection_handler::add_connection (this=0xb974aa0, channel_info=0xbd10b20)
at /data/repos/mysql-8.4.0/sql/conn_handler/connection_handler_per_thread.cc:421
4 0x000000000392a7a1 in Connection_handler_manager::process_new_connection (this=0xb125ad0, channel_info=0xbd10b20)
at /data/repos/mysql-8.4.0/sql/conn_handler/connection_handler_manager.cc:263
5 0x00000000033c2cfe in Connection_acceptor<Mysqld_socket_listener>::connection_event_loop (this=0xb9d0ea0)
at /data/repos/mysql-8.4.0/sql/conn_handler/connection_acceptor.h:66
6 0x00000000033b346c in mysqld_main (argc=6, argv=0x95163f8) at /data/repos/mysql-8.4.0/sql/mysqld.cc:9897
7 0x000000000339ec46 in main (argc=2, argv=0x7ffd9bd57448) at /data/repos/mysql-8.4.0/sql/main.cc:26