從RDS(相容MySQL)匯出資料案例分析

阿里雲柳璃發表於2014-06-05

作者:丁奇 

背景

MySQL全量邏輯備份恢復最基礎的方法,就是mysqldump生成文字,再通過source 命令直接匯入。一般用於例項遷移或者版本升級。

這裡說明最近碰到的一個失敗例子。

描述

這個例子可以簡要復現如下,在源庫上執行如下操作:

use mydb;

create table t1 (id int);

create view v1 as select * from t1;

drop table t1;

之後執行 mysqldump mydb,發現mysqldump中途退出。簡化後出錯原因很明顯,就是檢視v1對應的表t1已經不存在,這個檢視本身非法。

這個錯誤很危險,因為如果沒有捕獲這個錯誤,直接認為mysqldump執行完成,並將生成的結果應用於目標庫,則會導致資料丟失!

其實這個問題並不像看起來那麼簡單。

一個問題

mysqldump只需要生成show create view v1的結果即可—-這會導致在目標庫source的時候報錯—-為什麼會在dump的時候就報錯?

MySQL Tips: mysqldump匯出整庫,預設情況下,會在匯出前對整庫裡面的每個表加讀鎖,即Lock tables tb1 read, tb2 read,…, tbn read.

​本例中由於檢視v1需要的實體表t1已經不存在,lock table v1 read 返回失敗。因此整個庫所有表都沒有正常匯出。如果以此輸出結果匯入到目標庫,則整庫資料丟失。

MySQL Tips: mysqldump若正常結束,生成的檔案結果最後一行是“– Dump completed on + 時間”。

​使用dump的結果檔案必須先檢查結果檔案的完整性,判斷末行的文字是一個推薦操作。

導整庫的時候為什麼需要對所有表都加讀鎖呢?目的是為了得到一致性讀檢視。也就是說,在匯出整庫期間,不會有更新,這樣才保證匯出資料的一致性。

而實際上這個是歷史遺留問題,InnoDB本身支援一致性讀,也就是說只要啟動一個事務(begin/start transaction),則在此事務存續期間,對於本例項內InnoDB表的更新,此匯出事務均不可見。也就是說InnoDB事務可以保證事務期間看到的檢視與事務啟動瞬間看到的一致。

而鎖表會堵住更新,導庫又往往是長時間的操作,因此備份期間能允許讀寫對OLTP應用來說至關重要。

MySQL Tips: 若確保mysqldump匯出的資料中只有InnoDB表,可以用 –single-transaction 避免鎖表。

問題繼續

加了–single-transaction後不需要鎖表,是否還會導致mysqldump失敗?答案依然是會。這次我們發現輸出的錯誤是 “SHOW FIELDS FROM v1″ 失敗。由於show fields v1需要解析檢視並列出執行結果的列資訊,而表t1已經不存在因此報錯。

問題是,為什麼需要執行一個 SHOW FIELDS?

這就說到restore的依賴問題。

MySQL Tips: mysqldump生成匯出檔案時。同一個庫內實體表先生成,之後是檢視。多個實體表是按照字母升序生成,多個檢視也是按字母升序生成。

這樣就可能存在這樣的情況,某個檢視v1依賴檢視v2,而v1的字母排序前於v2。比如檢視名為x,而依賴的另一個檢視名為y。這樣在按順序輸出的時候,如果不做任何處理,在輸出檔案中就會先出現create view x …而由於x依賴於y但y還沒有生成,就會導致restore階段執行失敗。

MySQL Tips: mysqldump解決檢視依賴問題的方法,就是在生成實體表階段,如果碰到檢視,則建立一個同名的臨時實體表,該表的結果與檢視完全相同。

配合的策略是在生成真正的檢視前,先將臨時實體表刪除。這樣在restore階段,建立任何檢視V1前,它所依賴的檢視V2有兩種情況:

1) 字母排序V2 > V1,則當前庫中有一個名為V2的臨時實體表,這樣檢視V1能夠正常建立;

2) 字母排序V2 < V1,則此時檢視V2已經存在,這樣檢視V1能夠正常建立;

以上策略解決了檢視迴圈依賴的問題,這個機制需要早生成實體表階段得到檢視執行結果的列名,因此需要執行一個 SHOW FIELDS。

實踐建議

上面的分析說明了”為什麼”,以下操作型的讀者希望的實踐建議:

1) 為避免無效檢視影響匯出,可以在呼叫mysqldump時增加–force引數,強行忽略此錯誤。這個忽略不會對資料造成影響;

2) 使用–result-file引數儲存mysqldump結果,同時將所有控制檯收到的返回都作為報警返回給呼叫端;

3) 檢查 result-file的最後一行,若無“Dump completed on”字樣,則返回嚴重錯誤,終止備份恢復流程。

 


相關文章