前言
MySQL 服務啟動時讀取 my.ini (Windows) 或 my.cnf (Linux) 配置檔。合理的參數設定能發揮硬體最大效能,錯誤的配置則會導致 OOM、磁碟 IO 瓶頸、複寫中斷等嚴重故障。本文系統分類 80+ 核心參數,提供預設值、建議值、調校原理與生產環境範本,支援 MySQL 5.7/8.0。
一、配置檔結構與讀取順序
# Linux 讀取順序 (後者覆蓋前者)
/etc/my.cnf
/etc/mysql/my.cnf
/usr/etc/my.cnf
~/.my.cnf
# Windows
C:\Windows\my.ini
C:\my.ini
安裝目錄\my.ini
# 查看實際生效值
mysql> SHOW VARIABLES;
mysql> SHOW VARIABLES LIKE 'innodb_%';
二、核心參數分類詳解
■ 目錄與檔案
| 參數 | 預設值 | 建議值 | 說明 |
| basedir | 編譯時指定 | 安裝根目錄 | MySQL 安裝根目錄 |
| datadir | basedir/data | 獨立磁碟/掛載點 (如 /data/mysql) | 資料檔目錄,**務必與 OS/日誌分離** |
| tmpdir | /tmp | 獨立高速磁碟 (tmpfs/SSD) | 臨時表、排序檔目錄,避免 /tmp 滿盤 |
| socket | /var/lib/mysql/mysql.sock | /var/run/mysqld/mysql.sock | Unix Domain Socket 路徑,本地連線效能最佳 |
| pid-file | datadir/hostname.pid | /var/run/mysqld/mysqld.pid | PID 檔位置,systemd 管理需一致 |
| log-error | datadir/hostname.err | /var/log/mysql/error.log | 錯誤日誌路徑,**必須落盤持久化** |
| lower_case_table_names | 0 (Linux), 1 (Win) | 1 (跨平台相容) | 表名大小寫敏感度,1=不敏感 (小寫存儲) |
■ 連線與執行緒
| 參數 | 預設值 | 建議值 | 說明 |
| max_connections | 151 | 2000-5000 (視記憶體) | 最大連線數,**應用連線池上限 + 100** |
| max_user_connections | 0 (無限制) | 同 max_connections * 0.8 | 單用戶最大連線,防單一應用佔滿 |
| thread_cache_size | 自動 (8+) | 100-200 | 執行緒快取,**目標 Threads_created / Connections < 1%** |
| thread_stack | 256K/1M | 512K | 執行緒棧大小,複雜存儲程序需調大 |
| back_log | 自動 (50+) | 200-500 | 監聽隊列長度,高併發突發保護 |
| wait_timeout | 28800 (8h) | 300-600 (5-10min) | 非互動連線空閒斷開,**配合連線池驗證機制** |
| interactive_timeout | 28800 | 28800 | 互動式客戶端 (mysql CLI) 空閒時間 |
| max_connect_errors | 100 | 100000 | 連線錯誤阈值,防誤封 IP,需配合 flush-hosts |
■ 緩衝區與快取 (單連線/全域)
| 參數 | 範圍 | 預設值 | 建議值 (32GB RAM) | 說明 |
| sort_buffer_size | Session | 256K | 4-8M | ORDER BY/GROUP BY 排序緩衝,**超過則用磁碟臨時表** |
| read_buffer_size | Session | 128K | 2-4M | 全表掃描循序讀取緩衝 |
| read_rnd_buffer_size | Session | 256K | 4-8M | 排序後隨機讀取緩衝 (ORDER BY 索引掃描) |
| join_buffer_size | Session | 256K | 4-8M | 無索引 JOIN (Block Nested Loop) 緩衝,**慎調大** |
| binlog_cache_size | Session | 32K | 1-4M | 事務 Binlog 緩衝,**大事務需調大** |
| query_cache_size | Global | 0 (5.7), 移除 (8.0) | 0 (禁用) | 8.0 已移除,5.7 建議關閉避免鎖爭用 |
| table_open_cache | Global | 4000 | 8000-20000 | 表快取,**目標 Open_tables ≈ Table_open_cache** |
| table_definition_cache | Global | 1400 | 4000-10000 | .frm/結構定義快表,**表數量多必調大** |
| max_heap_table_size | Global | 16M | 256M | MEMORY 引擎/內部臨時表上限 |
| tmp_table_size | Global | 16M | 256M | 內部臨時表上限,**min(此值, max_heap_table_size)** 生效 |
■ InnoDB 核心參數 (效能核心)
| 參數 | 預設值 | 建議值 (32GB RAM) | 調校原則 |
| innodb_buffer_pool_size | 128M | 24G (75% 物理記憶體) | **最關鍵參數**,專用 DB 70-80%,混部 50-60% |
| innodb_buffer_pool_instances | 自動 (8) | 16-32 | 減少鎖爭用,每實例 ≥ 1GB,CPU 核心數為宜 |
| innodb_log_file_size | 48M | 4G | Redo Log 檔案大小,**總量 = Buffer Pool 25-50%**,大檔案減少 Checkpoint 壓力 |
| innodb_log_files_in_group | 2 | 2 | Redo Log 組檔案數,通常 2 足夠 |
| innodb_log_buffer_size | 16M | 256M-512M | 大事務/大 Blob 寫入需調大,避免頻繁 fsync |
| innodb_flush_log_at_trx_commit | 1 | 1 (核心業務) / 2 (可容忍 1s 丟失) | 1=最安全 (每提交 fsync),2=寫 OS 快取,0=每秒 fsync |
| innodb_flush_method | fsync | O_DIRECT | 繞過 OS 快取,避免雙重快取浪費記憶體,**需檔案系統支援** |
| innodb_file_per_table | ON | ON | 獨立 .ibd 檔案,支援表級空間回收、可移植表空間 |
| innodb_io_capacity | 200 | 4000-8000 (NVMe), 2000 (SSD), 200 (HDD) | 背景刷頁/清理 IOPS 能力,**誠實填寫磁碟實測值** |
| innodb_io_capacity_max | 2000 | 8000-16000 (NVMe) | 突發刷頁上限 |
| innodb_read_io_threads | 4 | 8-16 | 讀執行緒,NVMe 多調大 |
| innodb_write_io_threads | 4 | 8-16 | 寫執行緒 |
| innodb_page_cleaners | 4 | 4-8 | 頁面清理執行緒,≤ buffer_pool_instances |
| innodb_max_dirty_pages_pct | 90 | 90 | 髒頁比例上限,觸發積極刷頁 |
| innodb_max_dirty_pages_pct_lwm | 10 | 10 | 低水位,預先刷頁避免衝刷 |
| innodb_lock_wait_timeout | 50 | 5-10 (高併發) | 鎖等待超時,**短超時快速失敗、避免連鎖阻塞** |
| innodb_deadlock_detect | ON | ON | 死鎖偵測,極高併發可關閉改用 timeout |
| innodb_online_alter_log_max_size | 128M | 512M | Online DDL 臨時日誌上限,大表 DDL 需調大 |
■ Binlog 與複寫
| 參數 | 預設值 | 建議值 | 說明 |
| log_bin | OFF | ON (binlog/) | 啟用 Binlog,**複寫/時間點恢復必開** |
| binlog_format | ROW (8.0), MIXED (5.7) | ROW | ROW 格式最安全、支援複寫過濾、無非確定性函數問題 |
| binlog_expire_logs_seconds | 0 (永久) | 604800 (7天) / 2592000 (30天) | 自動清理過期 Binlog,**防止磁碟寫滿** |
| max_binlog_size | 1G | 1G | 單檔上限,達標自動輪轉 |
| sync_binlog | 1 (8.0), 0 (5.7) | 1 | 每提交 fsync Binlog,**數據零丟失核心參數** |
| binlog_rows_query_log_events | OFF | ON | 記錄原始 SQL 至 Binlog,利於審計/解析 |
| gtid_mode | OFF | ON | GTID 模式,**現代複寫架構基石** |
| enforce_gtid_consistency | OFF | ON | 強制 GTID 一致性 |
| slave_parallel_type | DATABASE | LOGICAL_CLOCK | 並行複寫策略,**LOGICAL_CLOCK 並行度最高** |
| slave_parallel_workers | 0 | 16-32 (CPU 核心數) | SQL 執行緒並行數,從庫追趕主庫關鍵 |
| slave_preserve_commit_order | OFF | ON | 保證提交順序,配合 LOGICAL_CLOCK 確保一致性讀 |
■ 安全與其它
| 參數 | 建議值 | 說明 |
| skip_name_resolve | ON | 禁用 DNS 反解,**消除連線建立延遲、避免 DNS 故障拖垮 DB** |
| skip_host_cache | ON | 配合 skip_name_resolve,不快取主機名 |
| local_infile | OFF | 禁用 LOAD DATA LOCAL,防任意檔案讀取攻擊 |
| sql_mode | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION | 嚴格模式,**防止隱式轉型、截斷靜默成功** |
| default_authentication_plugin | caching_sha2_password (8.0) | mysql_native_password (相容舊驅動) | 8.0 新認證插件,舊客戶端需調整 |
三、生產環境配置範本 (MySQL 8.0, 32GB RAM, NVMe SSD, 專用 DB)
[mysqld]
# === 基礎路徑 ===
basedir = /usr/local/mysql
datadir = /data/mysql
tmpdir = /tmp/mysql
socket = /var/run/mysqld/mysql.sock
pid-file = /var/run/mysqld/mysqld.pid
log-error = /var/log/mysql/error.log
lower_case_table_names = 1
# === 連線與執行緒 ===
max_connections = 3000
max_user_connections = 2500
thread_cache_size = 200
back_log = 500
wait_timeout = 300
interactive_timeout = 28800
max_connect_errors = 100000
# === 全域緩衝與快取 ===
table_open_cache = 16000
table_definition_cache = 8000
max_heap_table_size = 256M
tmp_table_size = 256M
# === Session 緩衝 (謹慎調大,總量 = Session數 × 大小) ===
sort_buffer_size = 4M
read_buffer_size = 2M
read_rnd_buffer_size = 4M
join_buffer_size = 4M
binlog_cache_size = 2M
# === InnoDB 核心 ===
innodb_buffer_pool_size = 24G
innodb_buffer_pool_instances = 16
innodb_log_file_size = 4G
innodb_log_files_in_group = 2
innodb_log_buffer_size = 512M
innodb_flush_log_at_trx_commit = 1
innodb_flush_method = O_DIRECT
innodb_file_per_table = ON
innodb_io_capacity = 6000
innodb_io_capacity_max = 12000
innodb_read_io_threads = 12
innodb_write_io_threads = 12
innodb_page_cleaners = 8
innodb_max_dirty_pages_pct = 90
innodb_max_dirty_pages_pct_lwm = 10
innodb_lock_wait_timeout = 5
innodb_online_alter_log_max_size = 512M
# === Binlog 與複寫 ===
log_bin = binlog/mysql-bin
binlog_format = ROW
binlog_expire_logs_seconds = 2592000
max_binlog_size = 1G
sync_binlog = 1
binlog_rows_query_log_events = ON
gtid_mode = ON
enforce_gtid_consistency = ON
slave_parallel_type = LOGICAL_CLOCK
slave_parallel_workers = 16
slave_preserve_commit_order = ON
log_slave_updates = ON
# === 安全與 SQL 模式 ===
skip_name_resolve = ON
skip_host_cache = ON
local_infile = OFF
sql_mode = ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
default_authentication_plugin = mysql_native_password
# === 字符集 ===
character_set_server = utf8mb4
collation_server = utf8mb4_unicode_ci
# === 慢查詢日誌 ===
slow_query_log = ON
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
log_queries_not_using_indexes = ON
log_throttle_queries_not_using_indexes = 100 # 限流,避免日誌爆炸
# === 其它優化 ===
open_files_limit = 65535
max_allowed_packet = 64M
net_buffer_length = 16K
bulk_insert_buffer_size = 64M
myisam_sort_buffer_size = 128M
key_buffer_size = 64M # 僅 MyISAM 系統表用
四、配置驗證與調優迴路
- 語法檢查:
mysqld --validate-config (8.0+) 或 mysqld --help --verbose 2>&1 | head -20。
- 啟動測試:
systemctl start mysqld,檢查 error.log 無 [ERROR]。
- 關鍵指標基線:記錄啟動後
SHOW GLOBAL STATUS 核心值。
- 壓測觀測:sysbench/TPCC 壓測,監控:
- Buffer Pool 命中率:
(Innodb_buffer_pool_read_requests - Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests > 99%
- 臨時表落盤率:
Created_tmp_disk_tables / Created_tmp_tables < 5%
- 排序落盤率:
Sort_merge_passes / Sort_scan < 1%
- 鎖等待:
Innodb_row_lock_waits、Innodb_row_lock_time_avg
- 微調迴路:根據瓶頸調整單一參數 → 重啟/線上修改 (動態參數) → 壓測驗證 → 固化配置。
五、常見配置錯誤與避坑
| 錯誤配置 | 後果 | 正確做法 |
| innodb_buffer_pool_size > 物理記憶體 80% | OS OOM Killer 殺死 mysqld | 預留 20%+ 給 OS、FS Cache、連線緩衝 |
| sort_buffer_size = 256M | 5000 連線佔用 1.25TB 記憶體 → OOM | Session 級參數保守 (4-8M),大排序用臨時表 |
| sync_binlog = 0 + innodb_flush_log_at_trx_commit = 2 | 掉電丟失 1 秒+ 數據,**雙重不安全** | 核心業務雙 1,非核心可雙 0/2 但需知風險 |
| 未設 binlog_expire_logs_seconds | 磁碟寫滿,MySQL 拒寫入、甚至損壞 | 必設 7-30 天,配合備份保留策略 |
| skip_name_resolve=ON 但 GRANT 用主機名 | 授權失效,無法連線 | GRANT 僅用 IP 或 %,或啟用 DNS 並確保解析穩定 |