鄭昀 創建於2015/12/2 最后更新於2015/12/4
關鍵詞:數據庫,MySQL,自動化運維,DDL,DML,SQL審核,備份,回滾,Inception,osc
提綱:
- 普通DBA和文藝DBA怎么做SQL審核
- 預執行庫如何實操
- Inception對備份/回滾服務器的特殊處理
每個大型互聯網公司都有一個數據庫自動化運維系統,比如 Qunar 有 Inception(已開源),美團也有,趕集網的3個 DBA 開發了一個變更自助發布系統,淘寶和新浪呢都叫 iDB,騰訊互動娛樂團隊有個 TMySQL。
大家都做這件事,一定是因為當數據量大到一定程度,數據重要到一定程度時,online schema change 和刷庫不容有失,第一解決鎖表問題,不能影響線上業務,第二搞定操作回滾問題,第三解救 DBA 於倒懸。我們的實現請參考《#研發解決方案#iDB-數據庫自動化運維平台》。
0x00,普通DBA和文藝DBA怎么做SQL審核
無論是 DDL 操作,還是數據訂正(也被稱為 DML 操作),都涉及 SQL 審核、預執行和數據備份及回滾。
1,普通 DBA 青年的做法是:
- Dev 或 CM 給 DBA 發執行腳本,
- DBA 肉眼審核,
- 語法錯誤/語義錯誤/不符合規范/……
- 駁回,修改,審核,再駁回,……,通過,
- DBA 執行前做一次全表備份,
- 援引 Inception 文檔的原話:
- 『備份是必要的,因為語句在沒有執行時,都是想不到它影響會有多大,一般是不需要,而需要時,才知道備份是多么的重要,這也正是應了一句諺語:“書到用時方恨少,事非經過不知難。”,但這個工作也很讓人為難,應該備份全表呢?還是把影響的查出來備份呢?DBA在這個時候肯定是不願意這樣做的,但萬一出問題怎么辦?都懂得,不說了。』
- 執行,
- Dev 或 QA 檢查,
- 收兵,或許有問題,則備份還原。
2,稍微文藝一些的 DBA 青年的做法是:
- Dev 或 CM 登錄自動化運維系統,提交 SQL 腳本,
- SQL 審核組件對腳本自動審核,檢查語法,檢查規范,
- DBA 點擊預執行,腳本在測試數據庫上 explain 或直接執行,獲得第一手數據,
- 影響行數,索引使用情況
- 預估執行時間
- DBA 確認無誤后,審核通過,系統按時在生產庫上執行,執行前系統將生產庫數據備份。
或者援引 Inception 文檔里的這張圖示意:

圖1 Inception的架構
0x01,預執行庫如何實操
我們雲縱對 iDB 的設想是,當審核 DDL 操作時,環境中部署一個預執行庫。當 iDB 上要做預執行時,iDB 程序調用命令行暫停預執行庫的同步,等預執行回滾之后恢復同步,避免因為表結構變化而同步停止。預執行庫不需要配置為 blackhole,因為我們需要真實數據來獲得執行耗時,來決定我們應以什么策略在線上自動執行。
下面展示一下預執行時審核詳情頁上點擊”生成執行明細“按鈕的效果:

我們可以在這里選一下“執行方式”,共有三種可選:
- nobinlog:適合我們的 Cobar 庫,合並庫和主站庫。先執行從庫,再執行主庫。從庫執行之后,會給30分鍾時間確認是否執行主庫。
- binlog:非 Cobar 庫操作。
- osc:對應於 MySQL 的在線 schema 修改工具 pt-online-schema-change。它先創建一個 tmp 表作為原表導數據的臨時表,然后在原表上建立三個觸發器,對應 Insert、Update、Delete 三種操作,再拷貝原表數據到臨時表中,Rename 原表為 old 表,再把臨時表 Rename 為原表,最后清理以上過程中不再使用的數據,如 old 表。它強調的是”在線更改表結構“,適合於大表。我們看一下 Inception 怎么做的:Inception 有一個設置項 inception_osc_min_table_size,默認為 16MB,表示表空間占用大於 16MB 時自動選擇 osc 方式執行。
0x02,Inception 對備份/回滾服務器的特殊處理
Inception 在做 DML 操作時,會將所有當前語句修改的行備份下來,存儲到一個指定的庫中。Qunar 在這里有一些特殊設計,值得借鑒。
下面文字搬運自他們的文檔:
備份數據在備份機器的存儲,是與線上被修改庫一對一的。但因為機器多(線上機器有很多)對一(備份機器只有一台),所以為了防止庫名的沖突,備份機器的庫名組成是由線上機器的 IP 地址的點換成下划線,再加上端口號,再加上庫名三部分,這三部分也是通過下划線連接起來的。例如:
192_168_1_1_3310_inceptiondb
一個備份庫,里面的表與對應線上表都是一一對應的,也就是說線上庫 inceptiondb 中有什么表,在備份庫 192_168_1_1_3310_inceptiondb 中就有什么表,表名也完全相同,不同的只是表中的列不同而已,它是用來存儲所有對這個表修改的回滾語句的,對應的表包括的列主要有下面兩個:
rollback_statement text:這個列存儲的是針對當前這個表的某一行被修改后,生成的這行修改的回滾語句。因為 binlog 是 Row 模式的,所以不管是什么語句,產生的回滾語句都是針對一行的,同時有可能一條語句的修改影響了多行,那么這里就會有多個回滾語句,但對應的是同一個 SQL 語句。對應關於通過下面的列來關聯起來。
opid_time varchar(50):這個列存儲的是的被執行的 SQL 語句在執行時的一個序列號,這個序列號由三部分組成:timestamp(int 值,是語句被執行的時間點),線上服務器執行時所產生的 thread_id,當前這條語句在所有被執行的語句塊中的一個序號。產生結果類似下面的樣子:1413347135_136_3,針對同一個語句影響多行的情況,那么所產生的多行數據中,這個列的值都是相同的,這樣就可以找到一條語句對應的所有被影響數據的回滾語句。
於是線上庫表結果與備份庫表結構的對應關系為:

圖2 Inception的備份服務器
-未完待續-
參考資源:
2,2014,isadba,pt-online-schema-change工具文藝用法;
3,2014,博客園-王滔,mysql在線修改表結構大數據表的風險與解決辦法歸納;
4,2011,楊挺,OSC 實現原理剖析;
5,2015,鄭昀,#研發解決方案#iDB-數據庫自動化運維平台;
