記錄從單機 1GB 內存頻繁 OOM,到多核 4GB+ 架構穩定支撐百萬 PV 的完整優化歷程。涵蓋硬件瓶頸分析、my.cnf 關鍵參數調優邏輯、實戰案例對比、避坑指南。
| 維度 | 瓶頸表現 | 解決方案 | 推薦配置 |
|---|---|---|---|
| 磁盤 I/O | iowait 高、查詢慢、頻繁卡頓 | RAID 0+1 / NVMe SSD / 閃存陣列 | NVMe SSD,RAID 10,避免 RAID 5 |
| CPU | sys% 高、併發處理慢 | SMP 多路對稱 CPU,開啟 HT | 2× Intel Xeon 2.4GHz+ (8-16 邏輯核心) |
| 內存 | Swap 活躍、OOM Killer 觸發 | 內存 ≥ 數據熱集大小 + 系統預留 | 生產庫 ≥ 4GB,核心庫 16-64GB+ |
[mysqld]
# === 基礎 ===
skip-name-resolve # 禁用 DNS,加速連接
skip-locking # 避免外部鎖
# === 連接層 ===
back_log = 384 # 突發連接隊列
max_connections = 768 # 最大連接,配合應用連接池
thread_cache_size = 64 # 線程複用,減少創建銷毀
thread_concurrency = 8 # 邏輯 CPU 數 × 2 (4核心×2=8)
# === InnoDB 核心 ===
innodb_buffer_pool_size = 2G # 物理內存 50-70%,核心參數
innodb_log_file_size = 256M # 大事務/高寫入調大
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 2 # 2=高性能(秒級丟失風險),金融必須 1
innodb_file_per_table = ON
innodb_thread_concurrency = 8
# === 緩存與排序 (每連接分配,總量=連接數×單值) ===
key_buffer_size = 256M # MyISAM 索引/系統表
sort_buffer_size = 6M # 排序緩存
read_buffer_size = 4M # 順序掃描
read_rnd_buffer_size = 16M # 隨機讀/範圍排序
join_buffer_size = 8M # 無索引 JOIN
# === 表與臨時表 ===
table_cache = 512 # 表緩存,配合 open_files_limit
tmp_table_size = 256M # 內存臨時表上限
max_heap_table_size = 256M
# === Query Cache (視業務) ===
query_cache_type = 1
query_cache_size = 64M
# === 慢查詢與二進制日誌 ===
long_query_time = 1
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
log_bin = mysql-bin
binlog_format = ROW
expire_logs_days = 7
# === 其他 ===
wait_timeout = 10 # 短連接快速回收
interactive_timeout = 10
Key_reads / Key_read_requests < 1/1000Qcache_lowmem_prunes 大 → 擴容;Qcache_hits 小 → 關閉。Qcache_free_blocks 佔比高 → 定期 FLUSH QUERY CACHE。Open_tables = table_cache 且 Opened_tables 持續增長 → 擴容。sort_buffer_size、join_buffer_size → 連接數×單值超過物理內存,導致 Swap/OOM。innodb_flush_log_at_trx_commit → 金融業務設為 2 導致數據丟失風險。ANALYZE TABLE → 統計信息過期,優化器選錯索引。innodb_buffer_pool_size 仍 2GB,資源浪費。
-- 緩存命中率
SELECT (1 - Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests) * 100 AS hit_rate;
-- 臨時表落盤率
SELECT Created_tmp_disk_tables / Created_tmp_tables * 100 AS disk_tmp_pct;
-- 排序落盤
SELECT Sort_merge_passes;
-- 線程複用率
SELECT Threads_created / Connections * 100 AS thread_create_pct;
-- 慢查詢趨勢
SELECT * FROM mysql.slow_log ORDER BY start_time DESC LIMIT 20;