MySQL 記憶體 = 全域共享 (InnoDB Buffer Pool、Key Buffer、Query Cache 等) + 線程獨享 (每連線獨立分配)。
**總記憶體 ≈ 全域共享 + (線程獨享 × max_connections)**。線程參數設過大是 OOM 主因。
| 參數 | 用途 | 預設值 | 調優建議 | 超限行為 |
|---|---|---|---|---|
| thread_stack | 線程棧 (遞歸、存儲過程、複雜查詢) | 256K (64位) | 256K-512K 足夠,深度遞歸才調大 | Stack overrun → Crash |
| sort_buffer_size | ORDER BY/GROUP BY/DISTINCT 排序緩衝 | 256K | 256K-2M。大排序臨時表落盤,EXPLAIN 看 Using filesort | 落盤臨時表 (慢) |
| join_buffer_size | 無索引 JOIN (ALL/index 掃描) 緩衝 | 256K | 256K-1M。有索引 JOIN 不用。大表 JOIN 慎調大,乘連線數極大 | 分批 JOIN (多次掃描被驅動表) |
| read_buffer_size | 全表掃描/全索引掃描順序讀取緩衝 | 128K | 128K-256K。大表順讀可適度調大 | 分批讀取 |
| read_rnd_buffer_size | 非順序讀取 (範圍查詢、排序後回表) 緩衝 | 256K | 256K-1M。大範圍查詢受益 | 分批讀取 |
| net_buffer_size | 通訊協議封包緩衝 (初始值) | 16K | 16K-64K。最大受限 max_allowed_packet (預設 4M/64M) | 動態增長至 max_allowed_packet |
| 參數 | 說明 |
|---|---|
| bulk_insert_buffer_size | 批次 INSERT ... VALUES(..),(..) / LOAD DATA INFILE 緩衝,MyISAM 專用,InnoDB 無效。預設 8M。 |
| tmp_table_size / max_heap_table_size | 內存臨時表大小上限。超過轉 MyISAM 磁盤表。取兩者較小值。建議 64M-256M,避免複雜查詢落盤。 |
全域共享:
innodb_buffer_pool_size = 128M
key_buffer_size = 16M
其他全域 ≈ 32M
合計 ≈ 176M
線程獨享 (保守估算):
sort_buffer_size = 256K
join_buffer_size = 256K
read_buffer_size = 128K
read_rnd_buffer_size = 256K
net_buffer_size = 16K (動態)
thread_stack = 256K
合計 ≈ 1.15 MB / 連線
可用記憶體給線程: 512M - 176M - OS(100M) ≈ 236M
最大連線數 ≈ 236M / 1.15M ≈ 205
建議 max_connections = 200 (留餘量)
-- 當前線程記憶體概估
SELECT
@@sort_buffer_size + @@join_buffer_size + @@read_buffer_size +
@@read_rnd_buffer_size + @@thread_stack AS per_thread_bytes;
-- 觀察實際併發
SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL STATUS LIKE 'Max_used_connections';
-- 臨時表落盤計數
SHOW GLOBAL STATUS LIKE 'Created_tmp_disk_tables';
Using filesort/Using temporary 且無法加索引優化時,酌情調大單參數。vm.swappiness=1,寧可拒絕連線 (Too many connections) 也不要 Swap 導致全系統凍結。線程獨享記憶體是「隱形殺手」,單連線毫無感覺,併發百線程即成災難。**以 max_connections 為總閘門,以 EXPLAIN 為調優羅盤,保守設定線程參數,將寶貴記憶體留給 InnoDB Buffer Pool**,是穩定高效的核心策略。