MySQL 運行於 Linux 之上,系統層資源的配置優化是資料庫效能的基石。本文從 CPU 調度、記憶體管理、磁碟 I/O、網路協議棧、後台服務精簡五大維度,提供生產環境驗證的調優參數、原理解析與驗證指令,構建系統級效能優化標準作業程序。
伺服器級 CPU 必須在最高主頻運行,節能模式會導致降頻、核心休眠,嚴重影響延遲敏感型資料庫負載。
# 方法 1:BIOS 層面關閉 (推薦,徹底)
# 進入 BIOS → Power Management → CPU Power Management → Disable C-States / Disable CPU Power Saving
# 方法 2:OS 層面關閉服務
systemctl disable --now cpupower # 或 cpuspeed
systemctl disable --now irqbalance # 中斷均衡在節能時會將中斷集中到非休眠核心,關閉後均勻分佈
# 驗證當前主頻
cat /proc/cpuinfo | grep "cpu MHz" | head -5
# 應接近 CPU 標稱最大主頻 (如 2.00GHz 顯示 1995+ MHz)
NUMA 架構下,CPU 與記憶體節點綁定。當本地節點記憶體不足時,MySQL 會觸發 Swap 而非跨節點訪問遠端記憶體,效能暴跌。
# 方法 1:BIOS 關閉 NUMA (視硬體支援)
# 方法 2:啟動 mysqld 時交織記憶體分配
numactl --interleave=all mysqld_safe --defaults-file=/etc/my.cnf &
# 或 systemd 服務修改
# /etc/systemd/system/mysqld.service
[Service]
ExecStartPre=/bin/bash -c "numactl --interleave=all true"
ExecStart=/usr/sbin/mysqld --defaults-file=/etc/my.cnf
# 驗證 NUMA 狀態
numastat -m | head -20
原理:interleave=all 將所有 NUMA 節點記憶體虛擬為統一池,繞過本地分配策略,兼具 SMP 共享優勢與 NUMA 延遲優勢。
# 1. 激進防 Swap (關鍵)
vm.swappiness = 1
# 注意:RHEL/CentOS 6.4+ 內核 vm.swappiness=0 可能觸發 OOM Killer,設為 1 最安全
# 2. 髒頁異步回寫閾值 (降低佔用記憶體)
vm.dirty_background_ratio = 5 # 預設 10%,降低觸發 pdflush 更早
vm.dirty_ratio = 15 # 預設 20%,降低同步回寫阻塞概率
# 3. 保護 mysqld 免受 OOM Killer
# 寫入啟動腳本或 systemd
echo -17 > /proc/$(pidof mysqld)/oom_score_adj
# oom_score_adj 範圍 -1000~1000,-1000 完全禁用 OOM,-17 極低優先級被殺
# 應用修改
sysctl -p
# 1. 計算所需 HugePages (以 2MB 頁面)
# MySQL 使用記憶體 = innodb_buffer_pool_size + innodb_log_buffer_size + key_buffer_size + max_connections * (sort_buffer_size + read_buffer_size + join_buffer_size) + 其他
# 假設需 20GB,頁面大小 2MB → 10240 頁面
# 2. 修改 /etc/sysctl.conf
vm.nr_hugepages = 10240
# 3. 分配鎖定記憶體權限給 mysql 用戶 (/etc/security/limits.conf)
mysql soft memlock unlimited
mysql hard memlock unlimited
# 4. my.cnf 啟用
[mysqld]
large-pages = 1
# 注意:HugePages 會鎖定物理記憶體,不可交換,過度分配會擠佔系統可用記憶體,需精確計算
| 文件系統 | RHEL/CentOS 7+ 建議 | 核心優勢 |
|---|---|---|
| XFS | 首選 | 並行 I/O 強、大文件支援好、延遲分配減少碎片、元數據操作快 |
| ext4 | 次選 | 成熟穩定、小文件較優、舊內核相容 |
# /etc/fstab 掛載選項 (關鍵)
/dev/nvme0n1p1 /data/mysql xfs defaults,noatime,nodiratime,inode64 0 0
# noatime/nodiratime:禁用訪問時間更新,大幅減少元數據寫入
# inode64:XFS 專用,避免 inode 集中在前 1TB 導致瓶頸
# 查看當前調度器
cat /sys/block/nvme0n1/queue/scheduler
# 輸出範例:[none] mq-deadline kyber (NVMe 多佇列無需傳統調度器)
# 輸出範例:mq-deadline kyber [none] (SSD 建議 none/kyber)
# 輸出範例:[cfq] deadline noop (HDD 建議 deadline)
# 臨時修改 (重啟失效)
echo none > /sys/block/nvme0n1/queue/scheduler # NVMe/SSD
echo deadline > /sys/block/sda/queue/scheduler # HDD
# 永久修改 (grub2)
# /etc/default/grub
GRUB_CMDLINE_LINUX="... elevator=deadline" # HDD
# 或 NVMe 不需 elevator 參數
grub2-mkconfig -o /boot/grub2/grub.cfg
選擇邏輯:NVMe 使用 none (無調度,硬體多佇列);SSD 使用 kyber/none;HDD 使用 deadline (截止時間調度,保證讀請求低延遲)。
datadir、innodb_log_file、tmpdir、binlog 掛載到不同物理裝置# 1. 全局 TCP 記憶體 (單位:頁,4KB)
net.ipv4.tcp_mem = 94500000 94500000 94500000 # min/pressure/max,約 360MB,按實際內存調整
# 2. 接收/發送緩衝區 (單位:字節)
net.ipv4.tcp_rmem = 4096 87380 67108864 # min/default/max (64MB)
net.ipv4.tcp_wmem = 4096 65536 67108864 # min/default/max (64MB)
# 3. Socket 緩衝區預設/最大
net.core.rmem_default = 262144
net.core.rmem_max = 67108864
net.core.wmem_default = 262144
net.core.wmem_max = 67108864
# 4. 連線隊列擴容
net.core.netdev_max_backlog = 10000 # 網卡接收隊列
net.core.somaxconn = 65535 # 全連接隊列 (accept 隊列)
net.ipv4.tcp_max_syn_backlog = 8192 # 半連接隊列 (SYN_RECV)
# 1. 啟用多隊列 (需驅動支援,現代 10G+ 網卡標配)
ethtool -L eth0 combined 8 # 設為 CPU 核心數或佇列數
# 2. Offload 卸載到網卡硬體 (減少 CPU 中斷)
ethtool -K eth0 rx on tx on tso on gso on gro on
# 3. 調大發送隊列
ifconfig eth0 txqueuelen 10000
# 4. MTU 巨型幀 (需交換機/路由器全鏈路支援 9000)
ifconfig eth0 mtu 9000 up
# 僅在確認應用層正確關閉連線 (發送 FIN) 後調整
net.ipv4.tcp_tw_reuse = 1 # 復用 TIME_WAIT sockets (新連線)
net.ipv4.tcp_tw_recycle = 0 # **禁用** (NAT 環境下導致連線失敗)
net.ipv4.tcp_fin_timeout = 15 # TIME_WAIT 縮短至 15s (預設 60s)
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
# 僅保留核心服務
systemctl disable --now postfix chronyd firewalld (改用 iptables/nftables) \
auditd kdump NetworkManager (靜態 IP 環境) \
cups bluetooth avahi-daemon ...
# 保留清單
systemctl enable --now sshd rsyslog crond network systemd-journald \
irqbalance (若 CPU 未關閉節能) \
mysqld prometheus-node-exporter (監控)
mpstat -P ALL 1、perf top、cat /proc/interrupts 檢查中斷均衡free -h、cat /proc/meminfo | grep -E 'Huge|Swap|Dirty'、pidstat -r -p $(pidof mysqld) 1iostat -xmt 1 (關注 %util、await、svctm)、iotopsar -n DEV 1、ss -s、netstat -s | grep -i 'listen\|syn\|timewait'SHOW ENGINE INNODB STATUS\G、SHOW GLOBAL STATUS LIKE 'Innodb%'系統層調優沒有銀彈,**「測量 → 瓶頸定位 → 針對性調整 → 驗證效果」**的閉環才是王道。將本攻略參數化為 Ansible/Playbook 腳本,納入新機器初始化標準流程,配合持續監控告警,才能讓 MySQL 在穩定的系統基石上發揮極致效能。