MySQL 每個客戶端連線對應一個線程,線程私有記憶體隨連線數線性增長。理解各 Buffer 用途、觸發條件與調優界限,是防止 OOM、提升查詢效能的關鍵。本文系統梳理 8 大線程獨享記憶體區。
| 記憶體區 | 控制參數 | 用途 | 觸發場景 | 調優建議 |
|---|---|---|---|---|
| 線程棧 | thread_stack | 線程 ID、運行上下文、函數調用棧 | 每連線必分配 | 預設 256K/1M 足夠,深度遞歸/存儲過程才需調大 |
| 排序緩衝 | sort_buffer_size | ORDER BY、GROUP BY、DISTINCT、filesort | 無法用索引排序時 | 預設 256K,複雜排序可調 1-4M,**避免設太大導致 OOM** |
| Join 緩衝 | join_buffer_size | Block Nested Loop Join(無索引 Join) | ALL/INDEX Join 時 | 預設 256K,大表 Join 可調 1-8M;有索引 Join 不會用到 |
| 順序讀緩衝 | read_buffer_size | 全表掃描、全索引掃描 | 無索引 WHERE、覆蓋索引掃描 | 預設 128K,順序讀密集場景可調 256K-1M |
| 隨機讀緩衡 | read_rnd_buffer_size | 索引查找回表、排序後回表、ORDER BY ... LIMIT | 非順序訪問數據頁 | 預設 256K,大量範圍查詢回表可調 512K-2M |
| 網路緩衝 | net_buffer_size | 連線資訊、結果集發送前暫存 | 每連線初始化、結果集產生 | 初始 16K,動態增長至 max_allowed_packet,通常無需調整 |
| 批量插入緩衝 | bulk_insert_buffer_size | INSERT ... VALUES(...),(...)、LOAD DATA INFILE | 多行 INSERT、載入檔案 | MyISAM 專用,預設 8M,大批量導入可調 32-64M |
| 臨時表記憶體 | tmp_table_sizemax_heap_table_size | 內部臨時表(GROUP BY、DISTINCT、UNION、衍生表) | 優化器決定用臨時表時 | 取兩者較小值為上限,超過自動轉 MyISAM 磁盤表;建議 32-64M |
總記憶體 ≈ 全局共享記憶體 + (連線數 × 線程獨享記憶體總和)
線程獨享總和 ≈ thread_stack + sort_buffer_size + join_buffer_size + read_buffer_size + read_rnd_buffer_size + net_buffer_size + bulk_insert_buffer_size + tmp_table_size
例:max_connections=4000,若每線程獨享 10MB → 40GB,**遠超實體記憶體**,必須克制參數。
sort_buffer_size=256K、join_buffer_size=256K、read_buffer_size=128K、read_rnd_buffer_size=256K、tmp_table_size=32M。SET SESSION sort_buffer_size=4M,避免影響全局。Performance Schema memory_summary_by_thread_by_event_name 觀察各線程峰值。tmp_table_size 預設 16M,max_heap_table_size 16M。bulk_insert_buffer_size 僅 MyISAM 生效,InnoDB 走 innodb_log_buffer_size/innodb_buffer_pool。精準掌控線程私有記憶體,讓 MySQL 在高併發下穩定、高效運行。