MySQL 臨時表分為內存表(MEMORY 引擎)與磁盤表(MyISAM/InnoDB)。磁盤臨時表產生大量 I/O,嚴重拖慢查詢。本文演示如何通過監控指標判斷問題、調整臨時表大小閾值、將 tmpdir 掛載至 tmpfs 內存盤,徹底消除磁盤臨時表 I/O 瓶頸。
SHOW GLOBAL STATUS LIKE 'Created_tmp%tables';
典型輸出:
| Variable_name | Value |
|---|---|
| Created_tmp_disk_tables | 49,094 |
| Created_tmp_tables | 37,842,181 |
磁盤臨時表佔比 ~0.13%,但絕對量大,若查詢複雜、排序/分組無索引,比例會飆升。
SHOW GLOBAL VARIABLES LIKE '%table_size';
| Variable_name | Value |
|---|---|
| max_heap_table_size | 25,165,824 (24 MB) |
| tmp_table_size | 25,165,824 (24 MB) |
規則:臨時表預估大小 < 兩參數較小值 → 內存 MEMORY 表;否則 → 磁盤 MyISAM 表。
陷阱:含 TEXT/BLOB 列、GROUP BY/ORDER BY 列超長、UNION 等場景,強制落磁盤,不受上述參數限制。
mkdir -p /mnt/ramdisk
chown mysql:mysql /mnt/ramdisk
mount -t tmpfs -o size=512M tmpfs /mnt/ramdisk
size=512M 根據物理內存與預估峰值臨時表總量設置,建議不超過物理內存 10-15%。
編輯 /etc/fstab:
tmpfs /mnt/ramdisk tmpfs rw,mode=1777,size=512M 0 0
/etc/my.cnf 或 /etc/mysql/my.cnf:
[mysqld]
tmpdir = /mnt/ramdisk
重啟 MySQL 生效:systemctl restart mysqld。
SHOW GLOBAL VARIABLES LIKE 'tmpdir';
輸出 /mnt/ramdisk 即成功。
Created_tmp_disk_tables 增長是否歸零。df -h /mnt/ramdisk 使用率,防止內存盤耗盡導致 OOM Killer 觸發。SQL_BUFFER_RESULT 或優化索引/ SQL,從源頭減少臨時表產生。將 tmpdir 遷移至 tmpfs 是解決磁盤臨時表 I/O 瓶頸的「外科手術式」方案,效果立竿見影。但需注意:內存盤數據掉電丟失(MySQL 重啟自動重建無影響)、容量規劃留足余量、優先從 SQL/索引層面減少臨時表產生。三管齊下,徹底消除臨時表性能隱患。