Linux 文件系统引起的云盘文件系统异常导致 MySQL 数据页损坏事故恢复复盘
事故的起因是因為當我訪問某個數(shù)據(jù)庫的某個表的時候,MySQL 立即出現(xiàn)崩潰并且去查看 MySQL 的錯誤日志出現(xiàn)類似信息
2019-05-09T05:52:19.232564Z 1027 [ERROR] InnoDB: Space id and page no stored in the page, read in are [page id: space=1668620387, page number=16777216], should be [page id: space=1321, page number=2560] 2019-05-09T05:52:19.232613Z 1027 [ERROR] InnoDB: Database page corruption on disk or a failed file read of page [page id: space=1321, page number=2560]. You may have to recover from a backup. 2019-05-09T05:52:19.232620Z 1027 [Note] InnoDB: Page dump in ascii and hex (16384 bytes):2019-05-09T05:52:19.301493Z 1027 [Note] InnoDB: Uncompressed page, stored checksum in field1 0, calculated checksums for field1: crc32 509574685/727399785, innodb 723696011, none 3735928559, stored checksum in field2 2940110097, calculated checksums for field2: crc32 509574685/727399785, innodb 2408125488, none 3735928559, page LSN 2131755008 16, low 4 bytes of LSN at page end 0, page number (if stored to page already) 16777216, space id (if created with >= MySQL-4.1.1 and stored already) 1668620387 InnoDB: Page may be a freshly allocated page 2019-05-09T05:52:19.301532Z 1027 [Note] InnoDB: It is also possible that your operating system has corrupted its own file cache and rebooting your computer removes the error. If the corrupt page is an index page. You can also try to fix the corruption by dumping, dropping, and reimporting the corrupt table. You can use CHECK TABLE to scan your table for corruption. Please refer to http://dev.mysql.com/doc/refman/5.7/en/forcing-innodb-recovery.html for information about forcing recovery. 2019-05-09T05:52:19.301558Z 1027 [ERROR] [FATAL] InnoDB: Aborting because of a corrupt database page in the system tablespace. Or, there was a failure in tagging the tablespace as corrupt. 2019-05-09 13:52:19 0x7fe307678700 InnoDB: Assertion failure in thread 140613058529024 in file ut0ut.cc line 942Trying to get some variables. Some pointers may be invalid and cause the dump to abort. Query (7fe2dc03c240): select * from desktop_document2 Connection ID (thread ID): 1027 Status: NOT_KILLED?
可以注意到這里就是 MySQL innodb 的數(shù)據(jù)發(fā)生了損壞。可以看到日志的最下面其實這里就是給出的是可能造成崩潰的 query?
這里我們可以看到是要因為對 desktop_document2 進行讀取造成的。一旦我們對該表嘗試讀寫或者 check table 都會造成 MySQL 崩潰重啟。
這里有兩種解決思路:
1. 有備份的話將備份找個地方恢復出來,然后重新生成該表。
2. 如果對應到壞的表 check 了之后發(fā)現(xiàn)是可有可無可以重新生成的表,可以直接將該表 drop 掉重建。這樣可以省出一些恢復的成本和復雜性。
3. 如果壞的數(shù)據(jù)不可修復,也沒有備份。那么需要避開壞數(shù)據(jù)用 id 偏移的方式盡量掃描更多的數(shù)據(jù)出來。
然后這里還有個腳本 可以批量掃描壞表。當遇到第一個壞表的時候檢查打印出來的 table_name 并做確認。然后排出掉他再繼續(xù)掃下面的表。
#!/bin/bash host_name=127.0.0.1 user_name= user_pwd= database= tables=$(/usr/local/webserver/mysql/bin/mysql -h$host_name -u$user_name -p$user_pwd $database -A -Bse "show tables") for table_name in $tables doecho $table_namecheck_result=$(/usr/local/webserver/mysql/bin/mysql -h$host_name -u$user_name -p$user_pwd $database -A -Bse "check table $table_name" | awk '{ print $4 }')if [ "$check_result" = "OK" ]thenecho "OK TABLE $table_name"fi done需要注意的是使用該腳本在掃描到壞表的時候同樣會觸發(fā) MySQL 異常重啟。
?
到目前為止來看似乎情況可控,但是遺憾的是造成這次事故繼續(xù)擴大的是。當時我發(fā)現(xiàn)異常損壞發(fā)生在系統(tǒng)盤,然后該盤有天級快照。在和各方確認該數(shù)據(jù)庫影響之后我打算直接使用 aliyun 的天級快照來恢復目前糟糕的情況。然后再重新計算當天的相關(guān)數(shù)據(jù)即可,恢復的周期也比較短。
于是關(guān)機開始恢復快照 然而等待我的卻是
exoo me????
看上去是引導區(qū)損壞了,到這里為止就感覺情況變得非常麻煩了。因為快照恢復之后出現(xiàn)這個問題就意味著之前很長一段時間一直都存在引導區(qū)因為文件系統(tǒng)損壞而損壞的情況。也就是說可能之前的快照也都壞了,系統(tǒng)盤無法作為引導啟動系統(tǒng)。
后來聯(lián)系 aliyun 工程師通過 liveCD 重啟系統(tǒng),將之前系統(tǒng)掛載到數(shù)據(jù)盤開始搶救數(shù)據(jù)。
這里有個值得反思的地方,當時沒有做這個機器的數(shù)據(jù)庫備份是因為想到有快照可以依賴,用快照來當備份使用。但是沒有考慮打的是,MySQL 的默認數(shù)據(jù)目錄是 /var/lib ,而這個目錄存在于數(shù)據(jù)庫上而并非數(shù)據(jù)盤上。一旦出現(xiàn)類似的文件系統(tǒng)或者引導區(qū)損壞重啟之后可能就無法進入系統(tǒng),最嚴重的情況可能無法使用快照恢復任何數(shù)據(jù)。
所以說任何時候即使有快照,都應該對你的數(shù)據(jù)庫進行最少天級備份。
?
在和 aliyun 確認一些信息之后,我列了一個恢復方案最終使用了方案2恢復了數(shù)據(jù)。下面貼一個 check list
方案1:1. data02 上用 data-11 5.8日凌晨3點的快照恢復一塊 500g 的數(shù)據(jù)盤。 2. data02 上配置和 data-11 上版本相同的 MySQL(5.7.23)。 3. 使用 data-11 上 MySQL 的數(shù)據(jù)目錄恢復出當時 MySQL 的情況并且啟動 MySQL 4. 使用 innobackupex 將機器上的數(shù)據(jù)庫全量備份出來,同時查看數(shù)據(jù)完整性情況,使用腳本 check table 檢查完整性。 5. 將 data-11 機器還原成初始配置,安裝同樣版本的數(shù)據(jù)庫,并且使用備份恢復數(shù)據(jù)庫數(shù)據(jù)。方案2:1. 直接在 data-11 上重置系統(tǒng)。?? 2. 然后使用鏡像掛一個 500g 的盤。?? 3. 通知 aliyun 工程師使得新掛載的盤變得可讀。?? 4. 安裝 MySQL 5.7.23 數(shù)據(jù)庫。?? 5. 將數(shù)據(jù)庫文件找個地方拷貝出來。?? 6. 將數(shù)據(jù)文件恢復至 新安裝的 5.7.23 數(shù)據(jù)庫,并且不保證相關(guān)賬號密碼都和以前一致。??這里要提一下方案2的todo 6,如果全量恢復整個數(shù)據(jù)庫的數(shù)據(jù),可以直接將整個數(shù)據(jù)目錄進行覆蓋,然后重啟數(shù)據(jù)庫就可以簡單的直接通過文件恢復數(shù)據(jù)庫。
如果是單純的要恢復某個表或者某個庫,最好還是找機器全量恢復之后,使用 mysqldump 或者 pxb 備份對應的庫表進行恢復比較簡單。直接通過恢復文件的形式恢復單個表庫實在太過于復雜了,感覺沒必要。
截止到目前數(shù)據(jù)庫就已經(jīng)恢復了,剩下的還是要 drop 掉壞掉的表進行重建,或者參照上面的方法進行數(shù)據(jù)搶救。
?
其實在之前一個月就發(fā)現(xiàn)該機器有一些奇怪的報錯日志 類似于
Aborted connection 134328328 to db: 'test' user: 'root' host: '127.0.0.1' (Got timeout reading communication packets)后來看了一些資料,這些都是一些網(wǎng)絡(luò)超時錯誤,與此次事故無關(guān),可以根據(jù)?http://mysql.taobao.org/monthly/2017/05/04/ |?https://www.percona.com/blog/2016/05/16/mysql-got-an-error-reading-communication-packet-errors/?來仔細排查網(wǎng)絡(luò)問題。
?
小結(jié):
不管有沒有快照或者別的保護措施都應該對數(shù)據(jù)庫進行天級備份,有備無患。
當能恢復接觸到數(shù)據(jù)的時候應該第一時間對數(shù)據(jù)進行再備份,保證至少當前狀態(tài)可以保證不再惡化。
要第一時間通知相關(guān)小伙伴事故處理的進度,以及通知到受影響的小伙伴獲得他們的支持,恢復之后第一時間恢復相關(guān)服務。
?
Reference:
https://zhuanlan.zhihu.com/p/60327406 ?MySQL通過frm、ibd文件恢復innodb數(shù)據(jù)
http://www.yunweipai.com/archives/19844.html ?MySQL 如何利用 ibd 文件恢復數(shù)據(jù)
http://mysql.taobao.org/monthly/2017/05/04/ ?MySQL · 答疑解惑 · MySQL 的那些網(wǎng)絡(luò)超時錯誤
https://www.percona.com/blog/2016/05/16/mysql-got-an-error-reading-communication-packet-errors/??mysql-got-an-error-reading-communication-packet-errors
https://dev.mysql.com/doc/refman/5.7/en/forcing-innodb-recovery.html ?Forcing InnoDB Recovery
?
轉(zhuǎn)載于:https://www.cnblogs.com/piperck/p/10844854.html
總結(jié)
以上是生活随笔為你收集整理的Linux 文件系统引起的云盘文件系统异常导致 MySQL 数据页损坏事故恢复复盘的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql的结构,段页区,及客户端命令
- 下一篇: 妈妈的考试