InnoDB 共享表空間 ibdata1 在大量刪除/更新後不會自動回收空間,導致檔案單調增長。本文詳述經典「備份-刪除-還原」壓縮流程、關鍵參數避坑,並介紹 MySQL 5.7+ 線上壓縮新特性與獨立表空間最佳實踐。
ibdata1 持續增長,即使 DELETE 大量資料、OPTIMIZE TABLE 也不縮小。.ibd 同樣受限。ibdata1 大小)。mysqldump --add-drop-table --single-transaction --flush-logs \
--default-character-set=latin1 --user=root -p \
--databases mydb > /backup/full_$(date +%F).sql
--single-transaction:InnoDB 熱備份不鎖表。--default-character-set:必須與資料庫實際字符集一致,否則中文亂碼。systemctl stop mysqldrm -f /var/lib/mysql/ibdata1 /var/lib/mysql/ib_logfile* /var/lib/mysql/mydb/
.frm 衝突。ibdata1、ib_logfile*。mysql -u root -p -e "CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql --user=root -p --default-character-set=latin1 mydb < /backup/full_$(date +%F).sql
ls -lh /var/lib/mysql/ibdata1 應顯著縮小;核心表 COUNT(*)、CHECKSUM TABLE 對比。| 坑點 | 後果 | 對策 |
|---|---|---|
| 字符集不匹配 | 中文亂碼、還原失敗 | 備份/還原雙端強制指定相同字符集 |
| 未刪除資料庫目錄 | 還原報錯 "Table already exists" | 連同目錄一併刪除 |
| 密碼含特殊字符 | 命令列解析錯誤 | 密碼用雙引號包裹:-p"pass word" |
| binlog 未清理 | 還原後 binlog 位置錯亂 | --flush-logs 備份前滾動日誌 |
| 從庫同步中斷 | 主從不一致 | 主庫操作前STOP SLAVE,操作後RESET SLAVE重建 |
-- 啟用獨立表空間(預設開啟)
SET GLOBAL innodb_file_per_table = 1;
-- 針對單表回收空間(線上、無鎖、5.6+ 支援)
ALTER TABLE `large_table` ENGINE=InnoDB;
-- 或使用 OPTIMIZE TABLE(5.7+ 線上重建)
OPTIMIZE TABLE `large_table`;
.ibd 檔案獨立)。ibdata1 **無法線上縮小**,仍需離線重建。innodb_file_per_table = 1(預設已開)。ALTER TABLE t ENGINE=InnoDB;(會產生 t.ibd)。ibdata1 僅存放系統資料(資料字典、Undo Log、雙寫緩衝),體積穩定在數百 MB 級。OPTIMIZE TABLE 解決,不再波及全局。innodb_undo_directory、innodb_undo_tablespaces:Undo Log 移出 ibdata1。innodb_max_undo_log_size + innodb_undo_log_truncate:自動截斷過大 Undo Log。ibdata1 暴漲問題。
ibdata1 膨脹
│
├─ MySQL 5.7+ 且表已獨立表空間? → ALTER TABLE ... ENGINE=InnoDB / OPTIMIZE TABLE(線上)
│
├─ 可接受停機窗口? → 經典備份-刪除-還原(全版本通用)
│
└─ 必須零停機且為共享表空間? →
1. 建新實例(獨立表空間)
2. 主從同步遷移數據
3. 切換流量
4. 棄舊實例
InnoDB 表空間管理核心原則:**預設獨立表空間、監控單表體積、線上回收單表、共享表空間僅存系統資料**。遵循此原則,ibdata1 膨脹將不再是運維噩夢。