基於 MySQL 5.1.7 原始碼(Windows VS2003 調試),以銀行櫃台類比,逐層剖析 MySQL 啟動核心流程:監聽埠建立、連線分發、執行緒快取/建立、命令迴圈、分發執行。
select() 等待新連線,accept() 接受,呼叫 create_new_thread()。cached_thread_count > wake_thread 喚醒快取執行緒(start_cached_thread),否則 pthread_create 建立新執行緒執行 handle_one_connection。while (!net->error && ...) 持續呼叫 do_command(),直到連線錯誤或 KILL。my_net_read() 讀取封包,解析命令碼,呼叫 dispatch_command()。COM_QUERY、COM_CONNECT、COM_QUIT 等)分發至對應處理函數。// 監聽迴圈
pthread_handler_t handle_connections_sockets(void *arg) {
while (!abort_loop) {
if (select((int)max_used_connection, &readFDs, 0, 0, 0) < 0) continue;
accept(sock, (struct sockaddr*)&cAddr, &length);
create_new_thread(thd);
}
}
// 執行緒建立/快取
static void create_new_thread(THD *thd) {
if (cached_thread_count > wake_thread) {
start_cached_thread(thd);
} else {
pthread_create(&thd->real_id, &connection_attrib, handle_one_connection, (void*)thd);
}
}
// 連線命令迴圈
pthread_handler_t handle_one_connection(void *arg) {
THD *thd = (THD*)arg;
while (!net->error && net->vio != 0 && !(thd->killed == THD::KILL_CONNECTION)) {
net->no_send_error = 0;
if (do_command(thd)) break;
}
}
// 讀取封包並分發
bool do_command(THD *thd) {
if ((packet_length = my_net_read(net)) == packet_error) return true;
return dispatch_command((enum enum_server_command)packet[0], thd, packet+1, packet_length);
}
原始碼閱讀建議:
• 從sql/mysqld.ccmain()入口追蹤初始化順序。
• 關注THD結構體,貫穿整個會話生命週期。
•vio抽象網路 IO,支援 SSL、Socket、Named Pipe 多種傳輸。
• 使用DBUG_ENTER/RETURN宏追蹤呼叫鏈。