當錯誤刪除了 MySQL 的 InnoDB 資料庫檔案 ibdata 及 ib_logfile, 如果 MySQL 伺服器仍在執行狀態, 而且資料可以照常寫入, 切記不要關閉 MySQL 伺服器或 kill 掉 mysqld, 這時還可以將 InnoDB 資料庫修復的, 以下記錄修復的步驟, 如果要測試, 切記在測試環境進行, 切勿在生產環境測試:
1. 先找出 mysqld 的 pid, 可以用 netstat 查詢:
1 2 |
# netstat -ntlp | grep mysqld tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 1921/mysqld |
上面的例子看到, mysqld 的 pid 是 1921.
2. 然後執行以下指令:
1 2 3 4 |
# ls -l /proc/1921/fd/ | grep -e ibdata -e ib_ lrwx------ 1 mysql mysql 64 Mar 24 17:30 3 -> /var/lib/mysql/ibdata1 lrwx------ 1 mysql mysql 64 Mar 24 17:30 8 -> /var/lib/mysql/ib_logfile0 lrwx------ 1 mysql mysql 64 Mar 24 17:30 9 -> /var/lib/mysql/ib_logfile1 |
要記下上面返回的結果, 上面例子只有 3 個檔案, 記下日期時間後的檔案名稱, 上面例子是 3, 8 及 9.
3. 以下步驟是登入 MySQL 並執行以下 MySQL 指令, 以下指令的作用是停止 MySQL 寫入工作:
1 2 |
mysql> FLUSH TABLES WITH READ LOCK; Query OK, 0 rows affected (0.335 sec) |
輸入以下指令加快停止的時間:
1 2 |
mysql> set global innodb_max_dirty_pages_pct=0; Query OK, 0 rows affected (0.01 sec) |
現在要等待所有 dirty pages 完全寫入硬碟, 用 “SHOW ENGINE INNODB STATUS” 查詢:
1 |
mysql> SHOW ENGINE INNODB STATUS; |
回傳的結果很長, 需要查看其中幾項, 以確保完全沒有寫入動作, 先看 “LOG” 段落 的 “Checkpoint age”, 當看到 “Checkpoint age” 是 “0” 才完成。
1 2 3 4 5 6 7 8 9 10 |
--- LOG --- Log sequence number 1597945 Log flushed up to 1597945 Last checkpoint at 1597945 Max checkpoint age 7782360 Checkpoint age target 7539162 Modified age 0 Checkpoint age 0 |
然後查看 “INSERT BUFFER AND ADAPTIVE HASH INDEX” 段落的 “Ibuf”, 數值需要等於 1:
1 2 3 4 |
------------------------------------- INSERT BUFFER AND ADAPTIVE HASH INDEX ------------------------------------- Ibuf: size 1, free list len 0, seg size 2, 0 merges |
另一個要檢查的項目是 TRANSACTIONS 段落, 確保 Purge 進程把 undo log 全部清除掉, 交易 ID 要一樣:
1 2 3 4 5 |
------------ TRANSACTIONS ------------ Trx id counter 500 Purge done for trx's n:o < 0 undo n:o < 0 |
確保 MySQL 完全沒有寫入工作後, 可以進行下一步, 複製 InnoDB 的檔案回資料庫目錄。
4. 把第 2 步看到的檔案複製到原來的 MySQL 目錄:
# cp 3 /var/lib/mysql/ibdata1
# cp 8 /var/lib/mysql/ib_logfile0
# cp 9 /var/lib/mysql/ib_logfile1
5. 修改檔案 owner 為 mysql:
6. 最後重新啟動 MySQL 伺服器: