事件起始
某夜,我正在床上冥想准備入睡,忽然同事向我求救:消息內容如下:
Oh My Gold 改了些配置,啥都沒了!都沒了!沒了!了!
我仔細詢問,原來是她因為某些原因將某庫的物理文件夾改名后,發現數據庫找不到了。於是又將名稱改回來。結果仍然找不到。這讓她覺得數據可能被損壞了,於是趕忙來找我修復。
修復過程
我們數據庫用的版本是 MySQL5.7 ,放置在Linux服務器上,在my.cnf 配置了數據庫物理文件的存放地址。存放於 data 文件夾下。
表的存儲引擎全部使用 InnoDB,data 目錄的文件依次如下
- 用數據庫名命名的文件夾,文件夾內存放的 *.ibd , *.frm 文件依次是數據庫表數據文件和表結構文件
- ibdata1 (存放InnoDB表元數據、undo logs、the change buffer, and the doublewrite buffer) 文件
- ib_logfile0 ,ib_logfile1 事務日志
這個時候我首先想到的是我本機用Navicat備份過一個文件,立刻打開Navicat嘗試還原備份,然而日志全是 Err錯誤,顯示表存在,但是我們是看不到的。這時候我就打算刪除該庫,直接使用備份恢復,然而數據庫刪除仍然報錯。我只得去備份了一下物理文件然后刪除。刪除后再使用Navicat還原
經過一番操作,數據庫文件是回來了。但是我電腦上的備份文件他不是實時的,雖然恢復了數據庫,但仍然丟失了部分數據,我心有不甘。於是我想了一個“妙計”: 我把剛才備份的物理文件里面的 .frm .ibd 文件替換到新創建的物理文件夾中。這樣狸貓換太子之后,我豈不是就擁有了最完整的數據?
說干就干,一通 cp -rf 過后,成功替換掉原來的文件。打開Navicat連接沒有問題,心里竊喜。就在這時,陸續有同事反應數據庫連不上了,我的天吶。什么鬼?我打開MoBa查看linux 進程,發現Mysql 服務已經宕掉了。我嘗試重啟,報出如下錯誤:
查看Mysql 錯誤日志:
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built,
or misconfigured. This error can also be caused by malfunctioning hardware.
Attempting to collect some information that could help diagnose the problem.
As this is a crash and something is definitely wrong, the information
collection process might fail.
經過上網查詢,說是可以通過在 my.cnf 添加如下的配置來強制啟動數據庫官方文檔對於該配置的解釋 ,同類問題的回答
[mysqld]
innodb_force_recovery = 1
-
1
(SRV_FORCE_IGNORE_CORRUPT
)使服務器即使檢測到損壞的頁也可以運行 。嘗試跳過損壞的索引記錄和頁,這有助於轉儲表。
-
2
(SRV_FORCE_NO_BACKGROUND
)阻止主線程和任何清除線程運行。如果在清除操作期間發生崩潰,則此恢復值可防止崩潰。
-
3
(SRV_FORCE_NO_TRX_UNDO
)崩潰恢復后 不運行事務回滾。
-
4
(SRV_FORCE_NO_IBUF_MERGE
)防止插入緩沖區合並操作。如果它們會導致崩潰,請不要這樣做。不計算表 統計信息。此值可能會永久損壞數據文件。使用此值后,准備刪除並重新創建所有二級索引。設置
InnoDB
為只讀。 -
5
(SRV_FORCE_NO_UNDO_LOG_SCAN
)啟動數據庫時 不查看撤消日志:
InnoDB
甚至將未完成的事務也視為已提交。此值可能會永久損壞數據文件。設置InnoDB
為只讀。 -
6
(SRV_FORCE_NO_LOG_REDO
)不進行與恢復有關的重做日志前回滾。此值可能會永久損壞數據文件。使數據庫頁面處於過時狀態,這又可能導致B樹和其他數據庫結構遭受更多破壞。設置
InnoDB
為只讀。
官方文檔特別說明:當級別 >= 4 時,可能會對數據庫文件造成不可挽回的破壞。我嘗試從1 開始逐步修改該值啟動。直到 6 才正常啟動。啟動后,只能執行查詢語句,增刪改都不行。於是我將數據庫文件全部備份后。關閉數據庫,刪除原來的 數據庫物理文件、ibdata1 文件、ib_logfile0 文件。之后將 innodb_force_recovery 值還原為默認值0。重新恢復了數據庫文件。解除了此次危機。
啟發
- 定時備份數據庫!即使是測試庫。測試庫可以調的時間間隔長一點
- 在不懂的情況下不要自作聰明亂動物理文件!