記一次從刪庫到恢復的經歷

翻身碼農把歌唱發表於2018-12-31

公司正在做社交專案,涉及到的各個端人員比較多,開發、運維、產品、測試20多個,當然,對大公司來說,20其實不算多,進入正題,我們資料庫使用的是MySQL,運維搭建的主從,而正是由於這個所謂的主從,害苦了開發的兄弟們;快取使用的是Redis,MySQL資料同步到Redis使用的是阿里開源的Canal,瞭解Canal的都知道,Canal是讀取MySQL的二進位制檔案,進而得到資料的變更,然後同步到Redis。

某天傍晚,後臺開發兄弟們日常更新,由於產品要求使用者的暱稱支援輸入表情,我們不得不修改MySQL的配置檔案,使其支援表情,修改了Master配置檔案,自然就需要修改Slave 的配置檔案,將Master重啟後,然後重啟Slave,都重啟後,發現master上的資料不能同步到slave了,我擦,不過由於專案剛剛起步,訪問量不大,加上天色已晚,後臺開發兄弟決定,不能同步就不能同步吧,明天找運維同事搞定。

第二天,運維同事瞭解情況後,連上伺服器,一頓操作。下午三點左右, 產品正在演示APP,說APP首頁沒有資料了,我們說,呵呵,怎麼可能,然後登上資料庫後,我我我擦,master 使用者表的資料被清空了,瞬間有點發毛,難道被攻擊了,趕緊看下 slave,我*,比master上的資料都乾淨,而此時的master 裡面的使用者表 還有幾條剛剛註冊進來的幾條資料,冷汗直流。快取,對,看下快取中,趕緊連上快取伺服器,疑問了,快取裡面 還有資料,master 使用者表的資料沒有了,而快取又是讀取的master裡面的二進位制檔案,先不考慮這個問題,目前的緊急問題是趕緊恢復資料。由於開啟了binlog,那就從這裡恢復,一同事趕緊下載binlog,瑪德,檔案太大,拉下來 將近40分鐘,這個方法暫緩。誒,快取不是有資料嘛,那就把快取裡面的資料重新寫到MySQL,趕緊寫一個for迴圈,從 丟失的資料的 ID 往前讀,然後一個個insert到資料庫,當然,這種方法會導致資料有點舊,不過,和資料完全丟失比起來,那就毛毛雨了。終於,歷經將近一小時,資料恢復。

資料恢復後,我們首要的目標就是查原因,原因無非就是兩個,一是被攻擊,二是內部人員所為。檢視MySQL的二進位制日誌,資料丟失大約是在3點左右,而伺服器是在曼谷,時間比北京時間晚一個小時,也就是伺服器上的時間是2點左右,拉二進位制檔案找原因,呵,太慢了,幾行命令搞定,

-- 檢視某個時間段的二進位制日誌,並且輸出到指定的檔案
mysqlbinlog --no-defaults --start-datetime="2018-12-12 13:00:00" --stop-datetime="2018-12-12 14:40:00" mysql-bin.000085 -vv --base64-output=decode-rows | more  >> target.txt

-- 將@1、@2等一系列看不懂的符號轉換為SQL語句
cat target.txt | sed -n '/###/p' | sed 's/### //g;s/\/\*.*/,/g;s/DELETE FROM/INSERT INTO/g;' | sed -r 's/(@4.*),/\1;/g' | sed 's/@[0-9]*\=//g' > test.sql
複製程式碼

然後將 test.sql 檔案拉下來,檢視,發現兩處可疑點(即兩條SQL),如下:

-- 建立一個像user一樣的表,user_bak
create table user_bak like user;
-- 刪除 user_bak
drop table user_bak;
複製程式碼

但是,沒有清空或者刪除user 表的sql,奇了怪了。突然,技術總監過來問,有沒有找到原因,我說還沒有,只是找到了兩條可疑的SQL,但是還沒發現有清空user的SQL,因為一直在看master上的日誌,因為是主從,看master 上的日誌和看slave上的一樣,然而,總監卻說,slave上的日誌也要查下,好吧,雖然覺得看了沒什麼用,誰讓他是老大呢。登上slave伺服器,卻發現,為什麼 slave 上也有二進位制日誌呢,先不管,看下日誌,發現有如下SQL:

-- 刪除 user
drop table user;
-- 建立user
create table user(
	...省略欄位
)
COMMENT='使用者表'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=4xxxxxx
;
複製程式碼

雖然打臉了,但是為什麼slave上也會有二進位制日誌呢,趕緊找運維問下到底是不是主從,運維說是,算了,還是看下配置檔案,呵呵,竟然是主主,不是說好的主從呢,怪不得在 slave上執行了 刪除使用者表,然後建立使用者表,建立的下一個自增點還是丟失前的自增點,master上使用者表的資料就不存在了,這樣Redis中資料存在的原因也破解了,Redis 讀取的是master中的二進位制檔案,正是由於從所謂的“從”刪除然後重建user表後(記錄到“從”的二進位制日誌),“主”上就有了user 表(記錄到“主”的中繼日誌,並沒有在這個“主”的二進位制日誌,所以 Canal根本沒有讀取到在“從”上的操作),原因是找到了,但是 是誰執行的呢??當我們正在討論的時候,運維說他在做測試,測試昨天的主從有沒有正常了,他在修復昨天不能主從複製的問題。

崩潰,修復就修復,執行刪除幹嘛,而說好的主從,咋還變成主主了,問題 原因找到了,意味著不用加班到天亮了。

這種問題一定要杜絕:

  • 非特殊情況,禁止使用ROOT賬戶;
  • 相關人員分配MySQL賬戶,制定許可權;
  • 禁止執行不帶條件的DELETE、UPDATE,TRUNCATE,DROP

歡迎關注我的公眾號~ 搜尋公眾號: 翻身碼農把歌唱 或者 掃描下方二維碼:

img

相關文章