MySQL 5.6 引入線程池,解決 One-Thread-Per-Connection 模式下的高併發痛點:線程頻繁創建/銷毀、高內存佔用、上下文切換風暴、鎖競爭加劇。線程池通過預創建固定數量線程、一線程服務多連接(最小調度單位為 Statement),在充分利用硬體資源前提下,平滑吸收連接洪峰,避免服務抖動。
MySQL 通過 thread_handling 參數切換:
NO_THREADS:主線程直連(調試用)ONE_THREAD_PER_CONNECTION:傳統模式POOL_OF_THREADS:線程池模式核心是 scheduler_functions 函數指針結構體,不同模式註冊不同回調實現:
struct scheduler_functions {
uint max_threads;
bool (*init)(void);
void (*add_connection)(THD *thd);
void (*thd_wait_begin)(THD *thd, int wait_type);
void (*thd_wait_end)(THD *thd);
bool (*end_thread)(THD *thd, bool cache_thread);
void (*end)(void);
// ... 其他回調
};
線程池模式註冊 tp_scheduler_functions,關鍵回調包括 tp_add_connection、tp_wait_begin/end、tp_init/end。

thread_pool_size 決定數量(通常=CPU 核心數),每 Group 一個 Listener 線程 + 多個 Worker 線程。| 參數 | 含義 | 建議值 |
|---|---|---|
| thread_handling | 調度模式 | pool-of-threads |
| thread_pool_size | Group 數量 | CPU 核心數 |
| thread_pool_stall_limit | Stall 檢測間隔(ms) | 500~1000 |
| thread_pool_idle_timeout | Worker 空閒退出時間(s) | 60 |
| thread_pool_oversubscribe | 每 Group 額外允許的活躍 Worker 數(不含 Listener) | 10~1000(視負載) |
| threadpool_high_prio_mode | 優先隊列策略 | transactions/statements |
connection 對象thread_id % group_count 決定歸屬 Groupget_event() 獲取請求handle_event() 處理thread_pool_idle_timeout),超時退出oversubscribe+1,超過則休眠epoll_wait 閒聽)THD 實例do_command() 循環處理epoll_wait() 阻塞監聽 Group 內所有連接 Socket
場景:事務 A 持有鎖但所在 Group 忙碌無法調度;事務 B 等待 A 的鎖卻能被調度 → 形成「調度死鎖」。
解決:引入優先隊列,持有鎖/活躍事務的請求優先入隊,Worker 先處理優先隊列,加速鎖釋放。
oversubscribe 上限,Timer 創建新 Worker 緩解,但根治需 SQL 限流/過濾。create_thread_to_handle_connection:從 Thread Cache 取線程或新建,入口 do_handle_one_connectiondo_handle_one_connection:循環 do_command() 讀取網絡包執行,直到 COM_QUITone_thread_per_connection_end:判斷是否歸還 Thread Cache,否則退出線程關鍵差異:傳統模式 Worker 自己 poll() 等待網絡包;線程池模式 Worker 專心處理,Listener 統一 epoll_wait 分發,**CPU 利用率更高**。
初始化:tp_init → thread_group_init → io_poll_create → epoll_create 關聯 Socket:handle_event → start_io → io_poll_associate_fd → epoll_ctl(ADD/MOD) 監聽循環:listener → io_poll_wait → epoll_wait 銷毀:tp_end → thread_group_close → close(pollfd)
註:epoll_ctl MOD 用於重新註冊已就緒的舊連接,因 epoll 觸發後會清空事件類型。
| 場景 | 調用鏈 |
|---|---|
| 創建 epoll | tp_init → thread_group_init → tp_set_threadpool_size → io_poll_create → epoll_create |
| 關閉 epoll | tp_end → thread_group_close → thread_group_destroy → close(pollfd) |
| 關聯 Socket | handle_event → start_io → io_poll_associate_fd → io_poll_start_read → epoll_ctl |
| 處理請求 | handle_event → threadpool_process_request → do_command → dispatch_command → mysql_parse → mysql_execute_command |
| Worker 空閒 | worker_main → get_event → pthread_cond_timedwait (等待 idle_timeout) |
| Listener 監聽 | worker_main → get_event → listener → io_poll_wait → epoll_wait |
| 端口監聽 | main → mysqld_main → handle_connections_sockets → poll |
MySQL 線程池通過 Group 化架構 + epoll 事件驅動 + 優先隊列 + Timer 守護,將「一連接一線程」重構為「N 連接 M 線程(M ≈ CPU 核心數)」,從根本上解決了高併發下的資源爭用與上下文切換瓶頸。理解其調度邏輯、關鍵參數、epoll 整合、死鎖優化,是 DBA 進行極致效能調優的必修課。