wtf!rds資料同步居然出問題了--小白db的資料修復歷程
由於一次上線操作的資料變更太多,導致執行時間很長!
由於做手動主從關係,所以操作落在了主庫上。
由於主從關係不是對整個庫的操作,所以在有表新增的地方,添加了新的同步關係。
db變更完成後,就釋出程式碼上線了!
以上是背景!一切看起來都很美好。
程式碼上線後,從從庫發現數據一直沒有,時間在一分分地過去。
我知道不能再等了,我從後臺直接進入主庫,檢視資料,正常寫入!
我知道是資料同步出問題了!媽蛋,說好的花錢買穩定呢?
同步出問題了,這讓我怎麼排查?我又不是dts的開發人員!
不過我還是想了幾個方向查一下:
1. 檢視同步任務,檢查是否有同步異常日誌;
2. 檢查目前的同步狀態,是否有異常;
3. 檢查同步流量情況,如果同步正常的話;
4. 檢查監控報警是否存在;
5. 檢查dts服務是否被黑名單了;
6. 如果實在不行,給阿里雲提交工單吧;
針對這幾個方向,著實是一個個落實了的。然而,結果是,不得而知。
1. 同步沒有日誌,why,可能是日誌太多沒意義吧!
2. 沒有發現異常,所有監控為空;
3. 由於我最開始做主從關係時,沒進行全量初始化資料,所以初始化狀態攔也為空;
4. 同步流量監控,基本為0,但是這貌似不能說明問題,才怪!
5. 重新把自己加入到報警人員中,期待出問題時收到訊息,不過最終並沒有收到過;
6. 檢查ip白名單問題,發現並無異常,而且資料庫程序中,也有dts服務存在;
7. 最終還是給阿里雲提交了工單,然而並沒有什麼卵用,迫在眉睫,還得自己先解決問題!
8. 懷疑是在做資料結構變更或者新增同步物件時,dts發生了異常,然而懷疑有毛用。反正又不能解決!
實在沒辦法,我覺得這個同步任務多半已經掛掉了,所以決定重新搞一個任務。也就是,把原來的同步任務刪掉,然後新建一個同步。雖然看到了很多警告,我還是幹了,沒辦法。重新設定任務,想勾選初始化資料和全量同步,結果失敗了。原因是,資料表已在目標庫中存在,可能存在衝突。
重新設定同步任務的過程,等待也是讓人著急。但不管怎麼樣,還是看到了同步中的狀態,發現從庫有資料了,但是僅僅是部分。抽查了幾個表資料後,發現某些表結構也不一樣,很自然的想到了,中間的資料同步已經被丟掉了。
我目前能快速做的,就是先主動把從庫表結構更改為一致狀態,以讓後續資料同步能順利進行。操作過程中,提示了很多錯誤,我完全忽略。但這在我最後的思考中,成了思路來源!
我把結構變更操作後,資料總算恢復了平靜,從庫資料寫入了。還不錯,從這一刻起,資料是正常的。
然而,這裡遇到了另一個更大的問題:資料一致性!兩個庫的資料不一致!(這是業界最為重視的話題之一)!不過幸好,這只是個從庫。但是有很多業務是從這個庫資料資料來源的,這絕逼會成為生產事故的啊。
事情也不算太糟,雖然db小白很著急,db老鳥們卻在笑:小場面,小場面!你不是主庫的資料來源是正確的嘛,同步過來就好了嘛!
是的,只要從主庫將資料搞一份過來就好了嘛!但是,怎麼搞?
和雖然聽過很多的道理,卻依舊過不好這一生一般。雖然你知道資料庫的n種操作姿勢,卻不一定能在關鍵的時候用出一招!
1. 一是最笨型姿勢:直接將從庫的資料刪除,從主庫裡把全裡資料導過來;即:備份&恢復!
2. 匯入的方式可以是自己dump,也可以利用dts進行全量初始化;
3. 二還是笨的:根據資料表時間點,匯出停頓時間段的資料,挨個匯入到從庫。這很危險,因為你可能匯入一些過期的資料;
4. 三使用dump資料匯入:使用mysqldump 根據特徵,取出資料,然後使用replace的方式,插入到從庫中;注意一些表項的設定!
# --skip-add-locks 不使用鎖進行表寫入。因為使用鎖時,極有可能導致更新花費很長時間!所以儘量將該引數帶上! # --skip-tz-utc 即不修改時區,資料庫裡儲存多少就是多少。因為本身兩個庫的資料是相當的,所以無需修改該引數! # -t 代表不建立表 mysqldump -uroot -t -p --skip-tz-utc --skip-add-locks--replace --host=localhost -w "1" --databases test > lostdata.dump
5. 使用dump時,引數設定最為關鍵,使用不當將導致資料取錯,或者直接更新錯誤;
四高階姿勢:既然資料同步是通過binlog做的,那麼,只要將binlog重新執行一遍,就好了嘛。但是風險同在,一是基於雲的服務貌似不提供這種功能;二是binlog重讀能保證結果一致嗎(冪等性),還得研究研究!
不管怎麼樣,用笨人的方式,最終還是讓資料保持一致了。
mysqldump過程中,幾點經驗之談:
1. 所有表儘可能新增公共特徵欄位,比如 update_time,這樣在同步的時候就可以方便使用where進行過濾了;
2. 可以以mysqldump作為命令,執行定時更新資料的指令碼;指令碼如下:
#!/bin/bash date_yesterday=`date '+%Y-%m-%d 00:00:00' -d '-1 day'`; date_before_yesterday=`date '+%Y-%m-%d 00:00:00' -d '-2 day'`; mysqldump -uroot -t -p --skip-tz-utc --skip-add-locks --replace --host=rm-xxx.mysql.rds.aliyuncs.com -w "update_time >= '$date_before_yesterday' AND update_time < '$date_yesterday'" --databases test --tables t_myusers > lastday.dump sed '/^USE `.*`;/d' lastday.dump > lastday.dump sed '/^CREATE DATABASE.*;/d' lastday.dump > lastday.dump mysql -uroot -p123 -Dtest_new <lastday.dump
這樣,就可以mysqldump來做簡單的備份,以及不實時的資料同步了!(調整頻率實現)
一句話總結:練為戰!