本文共 5630 字,大约阅读时间需要 18 分钟。
取名mypumpkin,是python封装的一个让mysqldump以多线程的方式导出库表,再以mysql命令多线程导入新库,用于成倍加快导出,特别是导入的速度。这一切只需要在 mysqldump 或 mysql 命令前面加上 mypumpkin.py
即可,所以称作魔法。
项目地址:
该程序源于需要对现网单库几百G的数据进行转移到新库,并对中间进行一些特殊操作(如字符集转换),无法容忍mysqldump导入速度。有人可能会提到为什么不用 mydumper,其实也尝试过它但还是放弃了,原因有:
另外有人还可能提到 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构造新的命令,模拟 <
操作。
参数解析从原来自己解析,到改用argparse模块,几乎做了一次重构。
对于没有指定--tables
的情况,程序会主动去库里查询一下所有表名,然后过滤进队列。 load in目标库,选项做到与dump out一样丰富,可以指定导入哪些db、哪些表、忽略哪些表。
其中的重点是做到与原mysqldump兼容,因为需要对与表有关的选项(-B
, -A
, --tables
, --ignore=
),进行分析并组合成新的执行命令,考虑的异常情况非常多。
重要:导出的数据不保证库级别的一致性
另,许多情况下我们导数据,并不需要完整的或者一致的数据,只是用于离线分析或临时导出,重点是快速拿数据给到开发。
db1 table1 table2db2 db3
即以上无法在命令行下判断 db1、table1 是库名还是表面,用的时候只需记住“[-A|-B], [--tables], [--ignore-table]”三组,必须出现一个:db1 table1 table2
改成db1 --tables table1 table2
,db2
改成-B db2 db3
。
安装基于python 2.7 开发,其它版本没测。需要按 MySQLdb 库。
./mypumpkin.py --helpOnly mysqldump or mysql allowed after mypumpkin.pyusage: mypumpkin.py {mysqldump|mysqls} [--help]This's a program that wrap mysqldump/mysql to make them dump-out/load-inconcurrently. 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 sqlfileAt least one of these 3 group options given: [-A,-B] [--tables] [--ignore-table]
--dump-dir
,必选项,原来用的shell标准输入输出 > or <
不允许使用。dump-dir指定目录不存在时会尝试自动创建。--threads=N
,N指定并发导出或导入线程数。dump out 默认线程数2, mypumpkin load in 默认线程数是 cpu个数 * 2。注:线程数不是越大越好,这里主要的衡量指标是网络带宽、磁盘IO、目标库IOPS,最好用 dstat 观察一下。-B
, --tables
,--ignore-table
,使用与mysqldump相同,如:
--tables
会覆盖--databases/-B
选项--tables
与--ignore-table
不能同时出现-B
,则--tables
或--ignore-table
必须紧跟db名之后导出:
## 导出源库所有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## 导出源库db1,db2,会从原库查询所有表名来过滤$ ./mypumpkin.py mysqldump -h dbhost_name -utest_user -pyourpassword -P3306 \ --single-transaction --opt -B db1 db2 --dump-dir visit_dumpdir2## 只导出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## 导出db1,db2库,但忽略 db1.t1, db2.t2, db2.t3表## mysqldump只支持--ignore-table=db1.t1这种,使用多个重复指令来指定多表。这里做了兼容扩展$ ./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
导入:
-A
, -B
, --tables
, --ignore-table
, --threads
, --dump-dir
用法与作用与上面完全相同,举部分例子: ## 导入dump-dir目录下所有表$ ./mypumpkin.py mysql -h dbhost_name -utest_user -pyourpassword --port 3307 -A \ --dump-dir=visit_dumpdir2## 导入db1库(所有表)$ ./mypumpkin.py mysql -h dbhost_name -utest_user -pyourpassword --port 3307 -B db1 \ --dump-dir=visit_dumpdir2## 只导入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## 导入db1,db2库,但忽略db1.t1表(会到dump-dir目录检查db1,db2有无对应的表存在,不在目标库检查)$ ./mypumpkin.py mysql -h dbhost_name -utest_user -pyourpassword --port 3307 \ -B db1 db2 --ignore-table=db1.t1 --dump-dir=visit_dumpdir2
转载地址:http://ivjml.baihongyu.com/