作者:付祥
現居珠海,主要負責 Oracle、MySQL、mongoDB 和 Redis 維護工作。
本文來源:原創投稿
*愛可生開源社群出品,原創內容未經授權不得隨意使用,轉載請聯絡小編並註明來源。
背景
線上一套 MySQL 計劃升級到 8.0 ,透過備份還原搭建一個測試環境,用於升級測試。資料庫採用 xtrabackup 每天進行全備,壓縮備份檔案約 300G ,解壓到一半就報錯了:
gzip: stdin: invalid compressed data--format violated
tar: Unexpected EOF in archive
tar: Unexpected EOF in archive
tar: Error is not recoverable: exiting now
剛開始以為只是這個備份檔案不完整,又找了前一天備份檔案,解壓過程中也報了同樣的錯誤,備份檔案比較大,無疑增加了排障時間。
故障分析
備份指令碼透過 crontab 每天凌晨執行,線上都是同一套備份指令碼,不同專案時常做備份資料還原,還是頭一次遇到備份檔案解壓失敗現象,檢視了指令碼,每個關鍵階段都做了狀態碼判斷是否成功,若失敗就告警,同時對 xtrabackup 備份日誌最後一行是否包含 completed OK 關鍵詞也做了判斷,關鍵備份指令碼如下:
xtrabackup xxx --stream=tar --no-timestamp $bkdir 2> xxx.log | gzip - > xxx.tar.gz
近期也沒收到失敗告警,說明備份指令碼是執行成功了的,感覺太奇怪了,檢視定時任務日誌,發現同一任務同一時間點竟然啟了2次:
[root@localhost backup]# grep backup /var/log/cron
Mar 6 00:00:01 localhost CROND[6212]: (root) CMD (sh xxx/mysql_ftp_backup.sh || echo 1 > xxx/err.log)
Mar 6 00:00:01 localhost CROND[6229]: (root) CMD (sh xxx/mysql_ftp_backup.sh || echo 1 > xxx/err.log)
Mar 7 00:00:01 localhost CROND[5387]: (root) CMD (sh xxx/mysql_ftp_backup.sh || echo 1 > xxx/err.log)
Mar 7 00:00:01 localhost CROND[5420]: (root) CMD (sh xxx/mysql_ftp_backup.sh || echo 1 > xxx/err.log)
crond 服務每次同時拉起2個程式執行備份,併發地往同一個壓縮檔案 xxx.tar.gz 寫資料,備份資料相互覆蓋,導致備份檔案損壞,每天看似備份成功的任務,其實備份都是無效的,這也說明瞭定期備份恢復演練的重要性。為何定時任務同一時間點會啟動2次?檢視 crond 程式:
[root@localhost backup]# ps -ef|grep crond |grep -v grep
root 2883 1 0 2018 ? 01:42:46 crond
root 17293 1 0 2022 ? 00:43:22 crond
原來是因為系統啟動了2個 crond 程式,kill crond 程式後重啟,再次檢視只有一個 crond 程式:
[root@localhost backup]# service crond stop
Stopping crond: [ OK ]
[root@localhost backup]# ps -ef|grep crond
root 2883 1 0 2018 ? 01:42:46 crond
root 31486 31856 0 10:59 pts/2 00:00:00 grep crond
[root@localhost backup]# kill 2883
[root@localhost backup]# ps -ef|grep crond
root 31572 31856 0 10:59 pts/2 00:00:00 grep crond
[root@localhost backup]# service crond start
Starting crond: [ OK ]
[root@localhost backup]# ps -ef|grep crond
root 31632 1 0 10:59 ? 00:00:00 crond
root 31639 31856 0 11:00 pts/2 00:00:00 grep crond
總結
為了確保備份有效,需要做如下改進:
1、flock給指令碼執行加互斥鎖,確保一個時間點只有1個程式執行。
2、定期做備份恢復演練。
3、增加crond程式監控,不等於1告警。