生產環境突發告警:/tmp 分區 100% 滿,大量複雜查詢因無法創建臨時表而失敗。根因:tmpdir 預設指向系統 /tmp (通常較小),大排序、分組、連接查詢產生的臨時表撐爆空間。本文記錄線上修改 tmpdir 至大容量數據盤的完整流程、熱修嘗試與生產環境最佳實踐。
-- 確認當前 tmpdir SHOW VARIABLES LIKE 'tmpdir'; -- 輸出: /tmp -- 查看佔用空間大的臨時文件 ls -lh /tmp/#sql* /tmp/ib* /tmp/mysql* 2>/dev/null | head -20 -- 當前運行的大查詢 SHOW FULL PROCESSLIST WHERE Command='Query' AND Time > 10;
| 方案 | 生效方式 | 需重啟 | 風險 | 適用場景 |
|---|---|---|---|---|
| 修改 my.cnf + 重啟 | 永久 | 是 | 服務中斷 | 維護窗口、非核心庫 |
| SET GLOBAL tmpdir | 運行時 | 否 | **不支援** (readonly) | 不可用 |
| 符號鏈接 /tmp → 大盤 | 即時 | 否 | 影響其他進程 | 緊急臨時 |
| 啟用 tmpfs 內存盤 | 掛載後 | 否 | 佔用內存、重啟丟失 | 高併發小臨時表 |
# 選擇大容量、高 IOPS 數據盤 mkdir -p /data/mysql/tmp chown mysql:mysql /data/mysql/tmp chmod 1777 /data/mysql/tmp # 粘滯位,防止誤刪
[mysqld] tmpdir=/data/mysql/tmp # 建議同時優化相關參數 tmp_table_size=256M max_heap_table_size=256M sort_buffer_size=8M read_rnd_buffer_size=4M
systemctl restart mysqldSHOW VARIABLES LIKE 'tmpdir' 生效SHOW VARIABLES LIKE 'tmpdir'; -- 輸出: /data/mysql/tmp -- 模擬大查詢驗證寫入 SELECT * FROM large_table ORDER BY non_indexed_col LIMIT 10; -- 觀察 /data/mysql/tmp 下生成 #sql* 臨時文件
# 停止寫入 /tmp 的查詢 (殺掉大查詢進程) # 移動現有 /tmp 內容 mv /tmp /tmp.bak # 創建符號鏈接 ln -s /data/mysql/tmp /tmp # 重新啟動受影響服務 (如有獨立 MySQL 實例) # 注意:影響所有使用 /tmp 的系統服務,謹慎使用!
# /etc/fstab tmpfs /data/mysql/tmp tmpfs defaults,size=4G,mode=1777,uid=mysql,gid=mysql 0 0 # 掛載 mount -a # 修改 my.cnf tmpdir=/data/mysql/tmp
適用場景:大量小臨時表、排序緩衝、內存充足 (建議 ≤ 總內存 10%)
風險:重啟丟失、OOM Killer 觸發、大臨時表直接落盤更穩健
# 納入 Prometheus node_exporter
# 告警規則
- alert: MySQLTmpdirDiskFull
expr: (node_filesystem_avail_bytes{mountpoint="/data/mysql/tmp"} / node_filesystem_size_bytes{mountpoint="/data/mysql/tmp"}) < 0.15
for: 5m
labels:
severity: critical
annotations:
summary: "MySQL tmpdir 剩餘空間 < 15%"
description: "請清理臨時文件或擴容 /data/mysql/tmp"
tmpdir=/data/mysql/tmp/3306chcon -R -t mysqld_db_t /data/mysql/tmp 或 setsebool -P mysql_connect_any 1tmp_table_size 過小導致臨時表頻繁落盤