取名mypumpkin,是python封裝的一個讓mysqldump以多線程的方式導出庫表,再以mysql指令多線程導入新庫,用于成倍加快導出,特别是導入的速度。這一切隻需要在 mysqldump 或 mysql 指令前面加上 <code>mypumpkin.py</code> 即可,是以稱作魔法。
該程式源于需要對現網單庫幾百g的資料進行轉移到新庫,并對中間進行一些特殊操作(如字元集轉換),無法容忍mysqldump導入速度。有人可能會提到為什麼不用 mydumper,其實也嘗試過它但還是放棄了,原因有:
不能設定字元集
沒有像 mysqldump 那樣靈活控制過濾選項(導哪些表、忽略哪些表)
因為資料量之巨大,而且将近70%是不變更的曆史表資料,這些表是可以提前導出轉換的;又有少量單表大于50g的,最好是分庫導出轉換。mydumper 不具備 mysqldump 這樣的靈活性
對忽略導出gtid資訊、觸發器等其它支援
阿裡雲rds 5.6 導出必須要設定 set-gtid-purged=off
另外有人還可能提到 mysqlpump —— 它才是我認為mysqldump應該具有的模樣,文法相容,基于表的并發導出。但是隻有 mysql服務端 5.7.9 以上才支援,這就是現實和理想的距離。。。
首先說明,mysqldump的導出速度并不慢,經測試能達到50m/s的速度,10g資料花費3分鐘的樣子,可以看到瓶頸在于網絡和磁盤io,再怎樣的導出工具也快不了多少,但是導入卻花了60分鐘,磁盤和網絡大概隻用到了20%,瓶頸在目标庫寫入速度(而一般順序寫入達不到iops限制),是以mypumpkin就誕生了 —— 兼顧myloader的導入速度和mysqldump導出的靈活性。
用python構造1個隊列,将需要導出的所有表一次放到隊列中,同時啟動n個python線程,各自從這個queue裡取出表名,subprocess調用作業系統的mysqldump指令,導出資料到以 dbname.tablename.sql 命名的檔案中。load in 與 dump out 類似,根據指定的庫名或表名,從dump_dir目錄找到所有sql檔案,壓進隊列,n個線程同時調用mysql構造新的指令,模拟 <code><</code> 操作。
參數解析從原來自己解析,到改用argparse子產品,幾乎做了一次重構。
對于沒有指定<code>--tables</code>的情況,程式會主動去庫裡查詢一下所有表名,然後過濾進隊列。
load in目标庫,選項做到與dump out一樣豐富,可以指定導入哪些db、哪些表、忽略哪些表。
其中的重點是做到與原mysqldump相容,因為需要對與表有關的選項(<code>-b</code>, <code>-a</code>, <code>--tables</code>, <code>--ignore=</code>),進行分析并組合成新的執行指令,考慮的異常情況非常多。
重要:導出的資料不保證庫級别的一緻性
對曆史不變表,是不影響的
具體到一個表能保證一緻性,這是mysqldump本身采用哪些選項決定的
不同表導出動作在不同的mysqldump指令中,無法保證事務。
在我的案例場景下,是有開發同學輔助使用一套binlog解析程式,等完成後重放所有變更,來保證最終一緻性。
另,許多情況下我們導資料,并不需要完整的或者一緻的資料,隻是用于離線分析或臨時導出,重點是快速拿資料給到開發。
不尋常選項識别
程式已經盡力做到與mysqldump指令相容,隻需要加上 mypumpkin.py、指定dump-dir,就完成并發魔法,但有些情況的參數不友善解析,暫不支援格式:
即以上無法在指令行下判斷 db1、table1 是庫名還是表面,用的時候隻需記住“[-a|-b], [--tables], [--ignore-table]”三組,必須出現一個:<code>db1 table1 table2</code>改成<code>db1 --tables table1 table2</code>,<code>db2</code>改成<code>-b db2 db3</code>。
密碼暫隻能顯式輸入
安裝基于python 2.7 開發,其它版本沒測。需要按 mysqldb 庫。
<code>--dump-dir</code>,必選項,原來用的shell标準輸入輸出 <code>> or <</code> 不允許使用。dump-dir指定目錄不存在時會嘗試自動建立。
<code>--threads=n</code>,n指定并發導出或導入線程數。dump out 預設線程數2, mypumpkin load in 預設線程數是 cpu個數 * 2。
注:線程數不是越大越好,這裡主要的衡量名額是網絡帶寬、磁盤io、目标庫iops,最好用 dstat 觀察一下。
<code>-b</code>, <code>--tables</code>,<code>--ignore-table</code>,使用與mysqldump相同,如:
在mysqldump裡面,<code>--tables</code>會覆寫<code>--databases/-b</code>選項
在mysqldump裡面,<code>--tables</code>與<code>--ignore-table</code>不能同時出現
在mysqldump裡面,如果沒有指定<code>-b</code>,則<code>--tables</code>或<code>--ignore-table</code>必須緊跟db名之後
其它選項,mypumpkin會原封不動的保留下來,放到shell去執行。是以如果其它選項有錯誤,檢查是交給原生mysqldump去做的,執行過程遇到一個失敗則會退出線程。
導出:
導入:
<code>-a</code>, <code>-b</code>, <code>--tables</code>, <code>--ignore-table</code>, <code>--threads</code>, <code>--dump-dir</code>用法與作用與上面完全相同,舉部分例子: