首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 臨時檔案與隱藏空間管理:TMPDIR、磁碟溢出防護與複寫安全

     編輯:MySQL 資料庫相關知識

臨時檔案產生場景與空間估算

操作類型臨時檔案用途最大空間估算公式典型風險
ORDER BY / GROUP BY 排序排序緩衝區溢寫磁碟 (filesort)(sort_length + row_pointer) × matched_rows × 2大結果集排序、缺乏索引
JOIN / 衍生表內部臨時表 (Internal temporary table)結果集大小 × 1.5-2 倍複雜多表連接、未命中索引
UNION / DISTINCT去重臨時表輸入行數 × 平均行長大量去重操作
ALTER TABLE / OPTIMIZE重建表臨時副本原表資料大小 + 索引大小大表結構變更、磁碟空間不足導致失敗
LOAD DATA INFILE資料轉換緩衝檔案大小 × 1.2巨型檔案導入
複寫從庫 SQL 執行緒複寫事件暫存、大事務拆分單事務 Binlog 大小大事務複寫延遲、從庫磁碟爆滿

TMPDIR 配置最佳實踐

1. 環境變數優先級

# 1. 啟動腳本/服務檔案設定 (最高優先級)
Environment="TMPDIR=/mnt/mysql_tmp"

# 2. my.cnf 參數 (次優先)
[mysqld]
tmpdir = /mnt/mysql_tmp:/mnt/mysql_tmp2:/mnt/mysql_tmp3  # 多路徑循環分佈 (5.1+)

# 3. 系統預設 (最低)
/tmp, /var/tmp, /usr/tmp

2. 多磁碟循環分佈 (關鍵優化)

  • 路徑必須位於 **不同物理磁碟** (NVMe / SSD / HDD),而非同磁碟不同分區
  • 格式:Linux 用冒號 `:` 分隔,Windows 用分號 `;`
  • 效果:並行排序/臨時表寫入自動輪詢分佈,提升 IOPS 吞吐、降低單盤壓力

3. 檔案系統選型建議

複寫從庫 tmpdir 禁忌與安全配置

❌ 絕對禁止

  • 將 tmpdir 指向 tmpfs (如 /dev/shm、/run/mysqld)
  • 指向掛載 noexec、nosuid 或啟動腳本會清空的目錄 (如 /tmp 被 systemd-tmpfiles 清理)

✅ 必須確保

  • 臨時檔案在 **mysqld 重啟後依然存在** (複寫從庫需保留 LOAD DATA INFILE 檔案、臨時表以便斷點續傳)
  • 目錄擁有者 mysql:mysql,權限 1777 (sticky bit 防止誤刪)
  • 磁碟空間 ≥ **最大單事務 Binlog 大小 × 2** + **最大排序臨時空間估算**

安全配置範例

[mysqld]
# 主庫:可用 tmpfs 加速小排序 (需足夠記憶體)
tmpdir = /dev/shm/mysql_tmp:/mnt/nvme1/mysql_tmp:/mnt/nvme2/mysql_tmp

# 從庫:嚴禁 tmpfs,使用持久化高效能磁碟陣列
tmpdir = /data/mysql_tmp1:/data/mysql_tmp2:/data/mysql_tmp3

# 目錄建立腳本 (啟動前執行)
mkdir -p /data/mysql_tmp{1,2,3}
chown mysql:mysql /data/mysql_tmp*
chmod 1777 /data/mysql_tmp*
# /etc/fstab 持久化掛載 (若為獨立磁碟)
/dev/nvme1n1 /data/mysql_tmp1 xfs defaults,noatime 0 2

磁碟溢出 (Disk Full) 自動處理機制

MySQL 內建行為

  1. 每 **60 秒** 檢查一次可用空間
  2. 每 **6 分鐘** 向錯誤日誌寫入警告:Disk is full writing '/mnt/tmp/MYxxxx' (Errcode: 28 - No space left on device)
  3. 若空間釋放,自動繼續寫入;否則線程持續阻塞

運維介入指令

# 1. 確認阻塞線程
SHOW PROCESSLIST;
-- 尋找 State: "Waiting for disk space" 或 "Writing to tmp table"

# 2. 釋放空間 (優先順序)
# 刪除舊備份、舊 Binlog (PURGE BINARY LOGS BEFORE '2024-01-01')
# 清理 /tmp、/var/tmp 無用檔案
# 擴容磁碟 / 掛載新磁碟至 tmpdir 路徑

# 3. 強制殺死阻塞線程 (最後手段)
KILL ;  -- 1 分鐘內生效

# 4. 觀察其他等待同表鎖的線程是否恢復
SHOW ENGINE INNODB STATUS \G  -- 關注 LOCK WAIT 區塊

監控與告警體系

# Prometheus mysqld_exporter 關鍵指標
mysql_global_status_created_tmp_tables        # 記憶體臨時表計數
mysql_global_status_created_tmp_disk_tables   # 磁碟臨時表計數 (關鍵!)
mysql_global_status_created_tmp_files         # 臨時檔案計數
mysql_global_status_sort_merge_passes         # 磁碟歸併排序次數

# 告警規則 (PromQL)
- alert: MySQLHighDiskTempTables
  expr: rate(mysql_global_status_created_tmp_disk_tables[5m]) > 10
  labels:
    severity: warning
  annotations:
    summary: "MySQL 磁碟臨時表建立率過高"
    description: "建議檢查索引、增加 sort_buffer_size、優化 SQL"

- alert: MySQLTmpDirDiskFull
  expr: (node_filesystem_avail_bytes{mountpoint=~"/mnt/mysql_tmp.*"} / node_filesystem_size_bytes{mountpoint=~"/mnt/mysql_tmp.*"}) < 0.15
  labels:
    severity: critical
  annotations:
    summary: "MySQL tmpdir 磁碟剩餘空間 < 15%"
    description: "立即清理或擴容,否則將導致查詢阻塞/失敗"

隱含臨時檔案可見性問題

MySQL 以 unlink 開啟檔案 (建立後立即刪除目錄項),導致 ls -la 無法看到佔用空間的大臨時檔案。

定位佔用空間的隱含檔案

# 方法 1: lsof 查看 mysqld 開啟的已刪除檔案
lsof -p $(pidof mysqld) | grep deleted

# 方法 2: /proc 探索
ls -l /proc/$(pidof mysqld)/fd/ | grep -E 'tmp|MY'

# 方法 3: 計算實際佔用
du -sh /mnt/mysql_tmp*  # 僅顯示目錄項存在的檔案
# 真實佔用 = df -h /mnt/mysql_tmp1 觀察 Used 差異
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
檔案系統優點缺點建議場景
ext4 / xfs穩定、支援大檔案、延遲分配元資料操作鎖競爭通用生產環境
tmpfs (記憶體檔案系統)極速、零磁碟 IO**重啟資料消失**、受限於記憶體大小**僅限主庫**、小型排序、足夠記憶體
ZFS / Btrfs壓縮、快照、校驗和CPU 開銷大、記憶體需求高備份/歸檔臨時目錄