The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

當 MySQL 的資料表使用 MyISAM 儲存引擎時要如何修復錯誤

上週我公司有台 Linux 突然 CPU 標高,且許多服務發生異常,經查發現有兩個 mysqld 程序個別耗用了 45% 左右的 CPU 時間,使用 uptime 查出平均負載竟然高達 100 多,我用 mysqladmin extended-status指令查不出任何異狀,接著就判斷可能是資料表毀損導致,接著我用 myisamchk 工具修復也無效,最後改用 REPAIR TABLE 語法才徹底解決問題。

發生問題時,我先下 SELECT COUNT(*) FROM TableName 是沒問題的,資料表有正常運作,接著我再下幾個含有 WHERE 篩選條件的 SQL 指令,發現回應的訊息如下:

mysql> SELECT COUNT(*) AS num FROM TableName WHERE group_id='33984' AND deleted = 'N';
ERROR 126 (HY000): Incorrect key file for table './DBNAME/TableName.MYI'; try to repair it

當時我是先用 myisamchk -e /var/lib/mysql/DBNAME/*.MYI 檢查所有資��表,有檢查出兩個表格出問題,然後進一步使用 myisamchk -r TableName.MYI 修復資料表,修復過程並沒有說明錯誤,我以為修好了,但過一段時間資料庫又再度掛點,然後再用 myisamchk -o -f TableName.MYI 強制修復也不行,這時才想到利用 MySQL 的 12.4.2.6. REPAIR TABLE Syntax 來修復資料表。

從得知有個 USE_FRM 選項,也就是當 myisamchk 無法修復 *.MYI 索引檔時,可以用這個選項來嘗試修復並重建 *.MYI 索引檔,執行的過程如下:

mysql> REPAIR TABLE TableName USE_FRM;
+--------------------+--------+----------+------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+--------------------+--------+----------+------------------------------------------+
| DBNAME.TableName | repair | warning | Number of rows changed from 0 to 4237067 |
| DBNAME.TableName | repair | status | OK |
+--------------------+--------+----------+------------------------------------------+
2 rows in set (3 min 56.73 sec)

執行完成後,所有表格就完全修復成功,系統也不再出問題了!

不過,使用 USE_FRM 選項有以下注意事項:

  • 僅在 *.MYI 檔案遺失 索引標頭損毀 (header corrupted) 時使用,而我這次的問題就是後者
  • 表格中原本使用 AUTO_INCREMENT 的欄位數值將會被重設,可能不會跟你原來的一樣!如果你的應用程式有參考到資料的 id 可能會需要再次檢查有無問題。例如:拿資料表中的 id 來建立目錄
  • 由於 *.MYI 索引標頭 會紀錄資料檔 ( *.MYD ) 是否為「壓縮資料表」,使用 USE_FRM 選項重建 *.MYI 索引檔可能會導致資料流失,也就是說你不應該使用 USE_FRM 選項重建壓縮資料表

相關連結