摘要:,指定并發(fā)導(dǎo)出或?qū)刖€程數(shù)。默認(rèn)線程數(shù),默認(rèn)線程數(shù)是個數(shù)。注線程數(shù)不是越大越好,這里主要的衡量指標(biāo)是網(wǎng)絡(luò)帶寬磁盤目標(biāo)庫,最好用觀察一下。
1. 簡介
取名mypumpkin,是python封裝的一個讓mysqldump以多線程的方式導(dǎo)出庫表,再以mysql命令多線程導(dǎo)入新庫,用于成倍加快導(dǎo)出,特別是導(dǎo)入的速度。這一切只需要在 mysqldump 或 mysql 命令前面加上 mypumpkin.py 即可,所以稱作魔法。
項目地址:https://github.com/seanlook/m...
該程序源于需要對現(xiàn)網(wǎng)單庫幾百G的數(shù)據(jù)進(jìn)行轉(zhuǎn)移到新庫,并對中間進(jìn)行一些特殊操作(如字符集轉(zhuǎn)換),無法容忍mysqldump導(dǎo)入速度。有人可能會提到為什么不用 mydumper,其實也嘗試過它但還是放棄了,原因有:
不能設(shè)置字符集
mydumper強(qiáng)制使用 binary 方式來連接庫以達(dá)到不關(guān)心備份恢復(fù)時的字符集問題,然而我的場景下需要特意以不同的字符集導(dǎo)出、再導(dǎo)入。寫這個程序的時候正好在公眾號看到網(wǎng)易有推送的一篇文章 (解密網(wǎng)易MySQL實例遷移高效完成背后的黑科技),提到他們對mydumper的改進(jìn)已支持字符集設(shè)置,可是在0.9.1版本的patch里還是沒找到。
沒有像 mysqldump 那樣靈活控制過濾選項(導(dǎo)哪些表、忽略哪些表)
因為數(shù)據(jù)量之巨大,而且將近70%是不變更的歷史表數(shù)據(jù),這些表是可以提前導(dǎo)出轉(zhuǎn)換的;又有少量單表大于50G的,最好是分庫導(dǎo)出轉(zhuǎn)換。mydumper 不具備 mysqldump 這樣的靈活性
對忽略導(dǎo)出gtid信息、觸發(fā)器等其它支持
阿里云rds 5.6 導(dǎo)出必須要設(shè)置 set-gtid-purged=OFF
另外有人還可能提到 mysqlpump —— 它才是我認(rèn)為mysqldump應(yīng)該具有的模樣,語法兼容,基于表的并發(fā)導(dǎo)出。但是只有 mysql服務(wù)端 5.7.9 以上才支持,這就是現(xiàn)實和理想的距離。。。
2. 實現(xiàn)方法首先說明,mysqldump的導(dǎo)出速度并不慢,經(jīng)測試能達(dá)到50M/s的速度,10G數(shù)據(jù)花費(fèi)3分鐘的樣子,可以看到瓶頸在于網(wǎng)絡(luò)和磁盤IO,再怎樣的導(dǎo)出工具也快不了多少,但是導(dǎo)入?yún)s花了60分鐘,磁盤和網(wǎng)絡(luò)大概只用到了20%,瓶頸在目標(biāo)庫寫入速度(而一般順序?qū)懭脒_(dá)不到IOPS限制),所以mypumpkin就誕生了 —— 兼顧myloader的導(dǎo)入速度和mysqldump導(dǎo)出的靈活性。
用python構(gòu)造1個隊列,將需要導(dǎo)出的所有表一次放到隊列中,同時啟動N個python線程,各自從這個Queue里取出表名,subprocess調(diào)用操作系統(tǒng)的mysqldump命令,導(dǎo)出數(shù)據(jù)到以 dbname.tablename.sql 命名的文件中。load in 與 dump out 類似,根據(jù)指定的庫名或表名,從dump_dir目錄找到所有sql文件,壓進(jìn)隊列,N個線程同時調(diào)用mysql構(gòu)造新的命令,模擬 < 操作。
參數(shù)解析從原來自己解析,到改用argparse模塊,幾乎做了一次重構(gòu)。
對于沒有指定--tables的情況,程序會主動去庫里查詢一下所有表名,然后過濾進(jìn)隊列。
load in目標(biāo)庫,選項做到與dump out一樣豐富,可以指定導(dǎo)入哪些db、哪些表、忽略哪些表。
其中的重點(diǎn)是做到與原mysqldump兼容,因為需要對與表有關(guān)的選項(-B, -A, --tables, --ignore=),進(jìn)行分析并組合成新的執(zhí)行命令,考慮的異常情況非常多。
3. 限制
重要:導(dǎo)出的數(shù)據(jù)不保證庫級別的一致性
對歷史不變表,是不影響的
具體到一個表能保證一致性,這是mysqldump本身采用哪些選項決定的
不同表導(dǎo)出動作在不同的mysqldump命令中,無法保證事務(wù)。
在我的案例場景下,是有開發(fā)同學(xué)輔助使用一套binlog解析程序,等完成后重放所有變更,來保證最終一致性。
另,許多情況下我們導(dǎo)數(shù)據(jù),并不需要完整的或者一致的數(shù)據(jù),只是用于離線分析或臨時導(dǎo)出,重點(diǎn)是快速拿數(shù)據(jù)給到開發(fā)。
不尋常選項識別
程序已經(jīng)盡力做到與mysqldump命令兼容,只需要加上 mypumpkin.py、指定dump-dir,就完成并發(fā)魔法,但有些情況的參數(shù)不方便解析,暫不支持格式:
db1 table1 table2 db2 db3
即以上無法在命令行下判斷 db1、table1 是庫名還是表面,用的時候只需記住“[-A|-B], [--tables], [--ignore-table]”三組,必須出現(xiàn)一個:db1 table1 table2改成db1 --tables table1 table2,db2改成-B db2 db3。
密碼暫只能顯式輸入
4. 使用說明安裝基于python 2.7 開發(fā),其它版本沒測。需要按 MySQLdb 庫。
4.1 help./mypumpkin.py --help Only mysqldump or mysql allowed after mypumpkin.py usage: mypumpkin.py {mysqldump|mysqls} [--help] This"s a program that wrap mysqldump/mysql to make them dump-out/load-in concurrently. Attention: it can not keep consistent for whole database(s). optional arguments: --help show this help message and exit -B db1 [db1 ...], --databases db1 [db1 ...] Dump one or more databases -A, --all-databases Dump all databases --tables t1 [t1 ...] Specifiy tables to dump. Override --databases (-B) --ignore-table db1.table1 [db1.table1 ...] Do not dump the specified table. (format like --ignore-table=dbname.tablename). Use the directive multiple times for more than one table to ignore. --threads =N Threads to dump out [2], or load in [CPUs*2]. --dump-dir DUMP_DIR Required. Directory to dump out (create if not exist), Or Where to load in sqlfile At least one of these 3 group options given: [-A,-B] [--tables] [--ignore-table]
--dump-dir,必選項,原來用的shell標(biāo)準(zhǔn)輸入輸出 > or < 不允許使用。dump-dir指定目錄不存在時會嘗試自動創(chuàng)建。
--threads=N,N指定并發(fā)導(dǎo)出或?qū)刖€程數(shù)。dump out 默認(rèn)線程數(shù)2, mypumpkin load in 默認(rèn)線程數(shù)是 cpu個數(shù) * 2。
注:線程數(shù)不是越大越好,這里主要的衡量指標(biāo)是網(wǎng)絡(luò)帶寬、磁盤IO、目標(biāo)庫IOPS,最好用 dstat 觀察一下。
-B, --tables,--ignore-table,使用與mysqldump相同,如:
在mysqldump里面,--tables會覆蓋--databases/-B選項
在mysqldump里面,--tables與--ignore-table不能同時出現(xiàn)
在mysqldump里面,如果沒有指定-B,則--tables或--ignore-table必須緊跟db名之后
其它選項,mypumpkin會原封不動的保留下來,放到shell去執(zhí)行。所以如果其它選項有錯誤,檢查是交給原生mysqldump去做的,執(zhí)行過程遇到一個失敗則會退出線程。
4.2 example導(dǎo)出:
## 導(dǎo)出源庫所有db到visit_dumpdir2目錄 (不包括information_schema和performance_schema) $ ./mypumpkin.py mysqldump -h dbhost_name -utest_user -pyourpassword -P3306 --single-transaction --opt -A --dump-dir visit_dumpdir2 ## 導(dǎo)出源庫db1,db2,會從原庫查詢所有表名來過濾 $ ./mypumpkin.py mysqldump -h dbhost_name -utest_user -pyourpassword -P3306 --single-transaction --opt -B db1 db2 --dump-dir visit_dumpdir2 ## 只導(dǎo)出db1庫的t1,t2表,如果指定表不存在則有提示 $ ./mypumpkin.py mysqldump -h dbhost_name -utest_user -pyourpassword -P3306 --single-transaction --opt -B db1 --tables t1 t2 --dump-dir visit_dumpdir2 ## 導(dǎo)出db1,db2庫,但忽略 db1.t1, db2.t2, db2.t3表 ## mysqldump只支持--ignore-table=db1.t1這種,使用多個重復(fù)指令來指定多表。這里做了兼容擴(kuò)展 $ ./mypumpkin.py mysqldump -h dbhost_name -utest_user -pyourpassword --single-transaction --opt -B db1 db2 --ignore-table=db1.t1 --ignore-table db2.t2 db2.t3 --dump-dir visit_dumpdir2 (如果-A表示全部db) ## 不帶 -A/-B $ ./mypumpkin.py mysqldump -h dbhost_name -utest_user -pyourpassword -P3306 --single-transaction --opt db1 --ignore-table=db1.t1 --dump-dir=visit_dumpdir2 ## 其它選項不做處理 $ ./mypumpkin.py mysqldump -h dbhost_name -utest_user -pyourpassword -P3306 --single-transaction --set-gtid-purged=OFF --no-set-names --skip-add-locks -e -q -t -n --skip-triggers --max-allowed-packet=134217728 --net-buffer-length=1638400 --default-character-set=latin1 --insert-ignore --hex-blob --no-autocommit db1 --tables t1 --dump-dir visit_dumpdir2
導(dǎo)入:
-A, -B, --tables, --ignore-table, --threads, --dump-dir用法與作用與上面完全相同,舉部分例子:
## 導(dǎo)入dump-dir目錄下所有表 $ ./mypumpkin.py mysql -h dbhost_name -utest_user -pyourpassword --port 3307 -A --dump-dir=visit_dumpdir2 ## 導(dǎo)入db1庫(所有表) $ ./mypumpkin.py mysql -h dbhost_name -utest_user -pyourpassword --port 3307 -B db1 --dump-dir=visit_dumpdir2 ## 只導(dǎo)入db.t1表 $ ./mypumpkin.py mysql -h dbhost_name -utest_user -pyourpassword --port 3307 --default-character-set=utf8mb4 --max-allowed-packet=134217728 --net-buffer-length=1638400 -B db1 --tables t1 --dump-dir=visit_dumpdir2 ## 導(dǎo)入db1,db2庫,但忽略db1.t1表(會到dump-dir目錄檢查db1,db2有無對應(yīng)的表存在,不在目標(biāo)庫檢查) $ ./mypumpkin.py mysql -h dbhost_name -utest_user -pyourpassword --port 3307 -B db1 db2 --ignore-table=db1.t1 --dump-dir=visit_dumpdir25.速度對比
原文鏈接地址:http://seanlook.com/2016/11/1...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/44277.html
閱讀 550·2021-08-31 09:45
閱讀 1661·2021-08-11 11:19
閱讀 895·2019-08-30 15:55
閱讀 833·2019-08-30 10:52
閱讀 2865·2019-08-29 13:11
閱讀 2937·2019-08-23 17:08
閱讀 2847·2019-08-23 15:11
閱讀 3077·2019-08-23 14:33