十年難得一遇!從數(shù)據(jù)誤刪到全量恢復(fù)的驚險(xiǎn)記錄
作者介紹
貝殼找房DBA團(tuán)隊(duì),負(fù)責(zé)支撐起貝殼找房平臺(tái)的數(shù)據(jù)庫(kù)運(yùn)維及數(shù)據(jù)庫(kù)產(chǎn)品的開發(fā)工作,努力提供高效、穩(wěn)定、安全的數(shù)據(jù)庫(kù)服務(wù)。
引言
線上的數(shù)據(jù)庫(kù)服務(wù)我們有完善的備份策略和恢復(fù)預(yù)案,數(shù)據(jù)即使被誤刪除了也是能夠恢復(fù)的,誤刪除的數(shù)據(jù)量恢復(fù)只是時(shí)間問(wèn)題。但各位同學(xué)自己部署的測(cè)試環(huán)境或者是在自己電腦中的開發(fā)環(huán)境的數(shù)據(jù)庫(kù)就沒有同級(jí)別的資源保障了。如果恰好你又把一些不能丟失的數(shù)據(jù)放到了這種環(huán)境中,那么建議要做定期備份,有備才能無(wú)患。
今天給大家分享的案例便是這種在線下自搭建環(huán)境的一次數(shù)據(jù)誤刪除事件。數(shù)據(jù)不幸被刪除和萬(wàn)幸能被全量恢復(fù)可謂十年一遇。
事件背景
測(cè)試環(huán)境中的一臺(tái)服務(wù)器準(zhǔn)備做遷移替換,小 A 同學(xué)接到了這個(gè)光(危)榮(險(xiǎn))的任務(wù)。小 A 選擇了直接 rm -rf /mysql 刪除這臺(tái)機(jī)器上掛載的數(shù)據(jù)分區(qū)來(lái)清理磁盤空間。
不到兩分鐘,還在挑燈夜戰(zhàn)的某位同學(xué)就發(fā)現(xiàn)一個(gè)常用的測(cè)試環(huán)境無(wú)法正常使用了。這時(shí)候的小 A 定是心如止(死)水(灰),還是找 DBA 幫忙看看吧。
值班 DBA 小 D 被電話叫起緊急支援,但小 D 登錄到服務(wù)器上一看也淡(傻)定(眼)了,數(shù)據(jù)、日志、軟件環(huán)境統(tǒng)統(tǒng)都被刪除了,唯一的一次備份是一年前升級(jí)測(cè)試環(huán)境數(shù)據(jù)庫(kù)時(shí)做的備份。給 DBA 老 A 打電話吧,問(wèn)問(wèn)他的建議。
恢復(fù)經(jīng)歷
一旦發(fā)生了誤刪數(shù)據(jù)先不要慌,停止所有操作,第一時(shí)間尋求幫助。即使您是老司機(jī),這時(shí)候也要找一位同學(xué)幫忙一起觀察后續(xù)的操作,避免手抖出現(xiàn)再次誤操作。
另外要強(qiáng)調(diào)的是,在出現(xiàn)數(shù)據(jù)誤刪除的服務(wù)器上同時(shí)只能有一個(gè)人操作,其他人應(yīng)通過(guò)桌面共享軟件或站在操作人身后觀察,避免多人交叉操作出現(xiàn)二次故障。
1、找回?cái)?shù)據(jù)文件
老 A 在得知數(shù)據(jù)、日志和軟件環(huán)境都被刪除后,先使用了 ps 命令查看 mysqld 進(jìn)程是否還存活。
進(jìn)程還在,這就有戲了,不幸中的萬(wàn)幸。抓緊到 /proc/${pid}/fd 目錄看看有沒有還未關(guān)閉的表可以搶救。
真是太幸運(yùn)了,這個(gè)測(cè)試環(huán)境里面的表比較少,所有表的數(shù)據(jù)文件還都是打開狀態(tài)。數(shù)據(jù)被找回的概率就很大了。接下來(lái)就是如何把這些顯示為 deleted 的文件從文件系統(tǒng)中找回了。
在介紹如何找回被刪除的文件前,先來(lái)介紹一個(gè)運(yùn)維經(jīng)常會(huì)遇到的刪除了文件,但磁盤空間不釋放的問(wèn)題。下圖是一個(gè)模擬的例子,當(dāng) test.txt 文件被 tail -f 命令使用時(shí),rm test.txt 并不會(huì)釋放空間,當(dāng)將 tail -f 命令 ctrl+c 中止后,磁盤空間才釋放。
一個(gè)文件在文件系統(tǒng)中的存放分為兩個(gè)部分:數(shù)據(jù)部分和指針部分,指針位于文件系統(tǒng)的 meta-data 中,數(shù)據(jù)被刪除后,這個(gè)指針就從 meta-data 中清除了,而數(shù)據(jù)部分存儲(chǔ)在磁盤中,數(shù)據(jù)對(duì)應(yīng)的指針從 meta-data 中清除后,文件數(shù)據(jù)部分占用的空間就可以被覆蓋并寫入新的內(nèi)容,之所以出現(xiàn)刪除 test.txt 文件后,空間還沒釋放,就是因?yàn)?tail -f 進(jìn)程還在一直打開這個(gè)文件句柄,文件對(duì)應(yīng)的指針部分由于進(jìn)程鎖定,并未從 meta-data 中清除。由于指針并未被刪除,那么系統(tǒng)內(nèi)核就認(rèn)為文件并未被刪除,因此通過(guò) df 命令查詢空間并未釋放。
有了之前遇到的類似經(jīng)驗(yàn)我們知道,MySQL 被刪除的數(shù)據(jù)由于句柄還在打開狀態(tài),因此還未完成刪除,是可以被找回的,已經(jīng)關(guān)閉的表就無(wú)法找回了。找回的方法也比較簡(jiǎn)單,直接 cat 對(duì)應(yīng)的文件句柄,再通過(guò)管道(pipe)或輸出重定向的方式即可找回原來(lái)的數(shù)據(jù)文件了。但要注意的是為了保證原來(lái)的磁盤不要再被寫入新的數(shù)據(jù),不要在原分區(qū)下做磁盤寫操作。這次的環(huán)境是部署在云服務(wù)器上的,再掛載一塊新的云盤到這臺(tái)服務(wù)器上就能把數(shù)據(jù)文件找回了,找回方式如下圖所示:
如果讀者使用的是自己的筆記本,可以插一塊 U 盤或移動(dòng)硬盤,將數(shù)據(jù)拷貝到 U 盤或移動(dòng)硬盤;如果使用的是物理機(jī)可以考慮使用管道給 netcat 命令把數(shù)據(jù)文件傳輸?shù)搅硗庖慌_(tái)服務(wù)器。如下圖所示:
表比較多的話建議寫個(gè)腳本進(jìn)行批量修復(fù),注意提前分好目錄結(jié)構(gòu),把對(duì)應(yīng)句柄的文件直接恢復(fù)到指定的目錄,便于后續(xù)處理。數(shù)據(jù)文件找回來(lái)啦!!!
2、恢復(fù)數(shù)據(jù)文件
數(shù)據(jù)文件已經(jīng)找回了,已經(jīng)算是完成了一半,至少業(yè)務(wù)的數(shù)據(jù)都在這些文件里面,但獨(dú)立的 ibd 文件是無(wú)法被 MySQL 識(shí)別的,需要配合表結(jié)構(gòu)定義文件(MySQL 5.7 之前為 frm 文件)才可使用。老 A 咨詢了業(yè)務(wù)同學(xué),他們使用的是開源的服務(wù),可以在其他環(huán)境上再部署一套,這樣就順利的拿到了這個(gè)服務(wù)的建表語(yǔ)句。
MySQL 5.6 以上版本支持通過(guò) ALTER TABLE xxx DISCARD TABLESPACE 和 ALTER TABLE xxx IMPORT TABLESPACE 的方式來(lái)刪除和導(dǎo)入表空間文件(ibd 數(shù)據(jù)文件)。而我們這次的測(cè)試環(huán)境剛好是 5.7 的版本,支持這種語(yǔ)法,真是太幸運(yùn)了。抓緊找個(gè)別的臨時(shí)環(huán)境來(lái)建表導(dǎo)入數(shù)據(jù)就好了。操作方式如下:
筆者在操作的時(shí)候使用的賬號(hào)不是 MySQL 賬號(hào),導(dǎo)致第 4 步在引入表空間的時(shí)候提示表空間不存在,修改文件屬主再重新導(dǎo)入就可以了。提醒大家還是要沉著,不要忙中出錯(cuò)。
3、重建環(huán)境
完成了上一步千萬(wàn)不要開心太早,由于原來(lái)的表空間是未正常關(guān)閉的,這種方式恢復(fù)的表不可直接使用,數(shù)據(jù)有無(wú)損壞還需要進(jìn)一步驗(yàn)證。這里老 A 建議把數(shù)據(jù)使用 mysqldump 出來(lái),然后再恢復(fù)到準(zhǔn)備遷移的新環(huán)境中。精力所限 MySQL 數(shù)據(jù)邏輯備份和恢復(fù)的方案這里就不再講解了,讀者可以自行搜索學(xué)習(xí)。
備份出來(lái)的數(shù)據(jù)表被導(dǎo)入到新環(huán)境后,老 A 請(qǐng)開發(fā)同學(xué)驗(yàn)證了里面的數(shù)據(jù),故障前最新的數(shù)據(jù)都還在,服務(wù)修改配置重新啟動(dòng)功能正常,這時(shí)業(yè)務(wù)終于長(zhǎng)出一口氣。
總結(jié)
老話說(shuō)“有備無(wú)患”,線上數(shù)據(jù)庫(kù)服務(wù)我們有每天的定時(shí)全量備份 ,還有基于 binlog 的實(shí)時(shí)增量備份。對(duì)于自已部署的環(huán)境也要加強(qiáng)備份意識(shí)。筆記本上的代碼要及時(shí)提交 git,產(chǎn)品文檔要及時(shí)上傳公司的云盤持久存儲(chǔ)。線上數(shù)據(jù)修改要提前備份修改前的內(nèi)容,刪除數(shù)據(jù)建議先標(biāo)記刪除再物理刪除。
本文轉(zhuǎn)載自微信公眾號(hào)「DBAplus社群」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系DBAplus社群公眾號(hào)。