公司以前在作東南亞社交項目,涉及到的各個端人員比較多,開發、運維、產品、測試20多個,固然,對大公司來講,20其實不算多,進入正題,咱們數據庫使用的是MySQL,運維搭建的主從,而正是因爲這個所謂的主從,害苦了開發的兄弟們;緩存使用的是Redis,MySQL數據同步到Redis使用的是阿里開源的Canal,瞭解Canal的都知道,Canal是讀取MySQL的二進制文件,進而獲得數據的變動,而後同步到Redis。mysql
某天傍晚,後臺開發兄弟們平常更新,因爲產品要求用戶的暱稱支持輸入表情,咱們不得不修改MySQL的配置文件,使其支持表情,修改了Master配置文件,天然就須要修改Slave 的配置文件,將Master重啓後,而後重啓Slave,都重啓後,發現master上的數據不能同步到slave了,我擦,不過因爲項目剛剛起步,訪問量不大,加上天色已晚,後臺開發兄弟決定,不能同步就不能同步吧,明天找運維同事搞定。sql
次日,運維同事瞭解狀況後,連上服務器,一頓操做。下午三點左右, 產品正在演示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
-- 將@一、@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根本沒有讀取到在「從」上的操做),緣由是找到了,可是 是誰執行的呢??當咱們正在討論的時候,運維說他在作測試,測試昨天的主從有沒有正常了,他在修復昨天不能主從複製的問題。測試
崩潰,修復就修復,執行刪除幹嗎,而說好的主從,咋還變成主主了,問題 緣由找到了,意味着不用加班到天亮了。spa
這種問題必定要杜絕:日誌