Mydumper是一个针对mysql和Drizzle的高性能多线程备份和恢复工具。开发人员分别来自MySQL,Facebook,SkySQL公司。目前已经在有一些大型产品业务上测试并使用了Mydumper。分稳定版和开发版两种,目前最新稳定版是0.2.3和最新开发版是0.5.1。恢复时可使用myloader工具。

Mydumper主要特性:

  1. 轻量级C语言写的代码
  2. mysqldump接近快10倍的速度
  3. 事务性和非事务性表一致的快照(适用于0.22+)
  4. 快速的文件压缩(file compression on-the-fly)
  5. 支持导出binlog
  6. 多线程恢复( 0.2.1+)
  7. 可以用守护进程的工作方式,定时的扫描和输出连续的二进制日志
  8. 开源 (GNU GPLv3)

mydumper安装方法:

wget http://launchpadlibrarian.net/77098505/mydumper-0.5.1.tar.gz

CentOS 6.0上测试的,安装前:

#yum install glib2-devel mysql-devel zlib-devel pcre-devel
#apt-get install libglib2.0-dev libmysqlclient15-dev zlib1g-dev libpcre3-dev(Ubuntu/Debian用户)
#tar -xzvf mydumper-0.5.1.tar.gz 
#cd mydumper-0.5.1 
#cmake . 
#make;make install

mydumper的使用和源代码分析

解析参数:

使用glib的g_option_context_parse,比libc里的getopt_long简单多了。连接目标数据库,通过show processlist来判断是否有长查询,如果有长查询则退出dump,可以通过–long-query-guard加长时间,或者使用–kill-long-queries杀掉长查询,锁定myisam表,针对innodb table开启事务。

产生3个消息队列(线程ready队列、任务队列、myisam表处理完毕队列)。

conf.queue = g_async_queue_new();
conf.ready = g_async_queue_new();
conf.unlock_tables= g_async_queue_new();

产生指定的线程个数,–threads可以指定,默认是4个。

GThread **threads = g_new(GThread*,num_threads);
struct thread_data *td= g_new(struct thread_data, num_threads);
for (n=0; n<num_threads; n++) {
td[n].conf= &conf;
td[n].thread_id= n+1;
threads[n] = g_thread_create((GThreadFunc)process_queue,&td[n],TRUE,NULL);
g_async_queue_pop(conf.ready);
}

dump_database,从DATA_DICTIONARY.TABLES读取所有表,通过–ignore, –tables-list, regex等过滤条件,产生需要dump的目标表列表,分别插入innodb_tables、non_innodb_table、table_schemas三个链表。

query= g_strdup_printf("SELECT TABLE_NAME, ENGINE, TABLE_TYPE as COMMENT FROM DATA_DICTIONARY.TABLES WHERE TABLE_SCHEMA='%s'", database);
....
innodb_tables= g_list_append(innodb_tables, dbt);
....
non_innodb_table= g_list_append(non_innodb_table, dbt);
....
table_schemas= g_list_append(table_schemas, dbt);

dump non-innodb table 把需要导出myisam表加入到任务队列。

for (non_innodb_table= g_list_first(non_innodb_table); non_innodb_table; non_innodb_table= g_list_next(non_innodb_table)) {
dbt= (struct db_table*) non_innodb_table->data;
dump_table(conn, dbt->database, dbt->table, &conf, FALSE);
g_atomic_int_inc(&non_innodb_table_counter);
}

dump innodb table把需要导出innodb表加入任务队列。

for (innodb_tables= g_list_first(innodb_tables); innodb_tables; innodb_tables= g_list_next(innodb_tables)) {
dbt= (struct db_table*) innodb_tables->data;
dump_table(conn, dbt->database, dbt->table, &conf, TRUE);
}

dump schema 把需要导出表结构任务加入到任务队列。

for (table_schemas= g_list_first(table_schemas); table_schemas; table_schemas= g_list_next(table_schemas)) {
dbt= (struct db_table*) table_schemas->data;
dump_schema(dbt->database, dbt->table, &conf);
g_free(dbt->table);
g_free(dbt->database);
g_free(dbt);
}

典型的生产者(主线程)消费者(子线程)模式,子线程会从任务队列里读取需要处理的表名字和表类型,再通过select * from table_name 读入数据各自写入到各自的文件。

for(;;) {
....
job=(struct job *)g_async_queue_pop(conf->queue);
....
switch (job->type) {
case JOB_DUMP:
....
dump_table_data_file(thrconn, tj->database, tj->table, tj->where, tj->filename);
....
case JOB_DUMP_NON_INNODB:
....
dump_table_data_file(thrconn, tj->database, tj->table, tj->where, tj->filename);
case JOB_SCHEMA:
....
dump_schema_data(thrconn, sj->database, sj->table, sj->filename);
}

所有导数据的任务加入任务队列之后,会再加入让线程退出的任务,让线程自然退出。

case JOB_SHUTDOWN:
g_message("Thread %d shutting down", td->thread_id);
if (thrconn)
mysql_close(thrconn);
g_free(job);
mysql_thread_end();
return NULL;
break;

解除myisam表锁,等待子线程退出。

使用

导出test database的数据

mydumper -h 127.0.0.1 -u root --database test

指定某个目录

mydumper -h 127.0.0.1 -u root --outputdir=.

不导出表结构

mydumper -h 127.0.0.1 -u root --no-schema

如果表数据是空,还是产生一个空文件(默认无数据则只有表结构文件)

mydumper -h 127.0.0.1 -u root --build-empty-files

设置长查询的上限,如果存在比这个还长的查询则退出mydumper,也可以设置杀掉这个长查询

mydumper -h 127.0.0.1 -u root --long-query-guard 200 --kill-long-queries

设置要dump的列表–tables-list,不需要设置db名字,逗号分割

mydumper -h 127.0.0.1 -u root --tables-list=ddd,zzz

通过regex也设置正则表达,需要设置db名字

mydumper -h 127.0.0.1 -u root --regex=test.z

把单表分成多个chunks,这个后面会讲分割的原理

mydumper -h 127.0.0.1 -u root --rows 10000

过滤某个引擎的表

mydumper -h 127.0.0.1 -u root -B test --ignore-engines=innodb

详细日志

mydumper -h 127.0.0.1 -u root -B test -v 3

几个注意点

各自线程都要自己连接到数据库,因为libmysql是线程不安全的。
因为对myisam表有有表锁,所有先处理myisam表,记录myisam表个数,每处理一个myisam都原子操作数量减一。并在myisam表都处理完毕后,立即解锁,尽量减少锁定的时间,而不是在导出innodb表数据的时候还在lock myisam表。

main_thread

for (non_innodb_table= g_list_first(non_innodb_table); non_innodb_table; non_innodb_table= g_list_next(non_innodb_table)) {
dbt= (struct db_table*) non_innodb_table->data;
dump_table(conn, dbt->database, dbt->table, &conf, FALSE);
g_atomic_int_inc(&non_innodb_table_counter);
}

child_thread

if (g_atomic_int_dec_and_test(&non_innodb_table_counter) && g_atomic_int_get(&non_innodb_done)) {
g_async_queue_push(conf->unlock_tables, GINT_TO_POINTER(1));
}

main_thread

g_async_queue_pop(conf.unlock_tables);
g_message("Non-InnoDB dump complete, unlocking tables");
mysql_query(conn, "UNLOCK TABLES");

–regex的处理在–tables-list后, 先满足–tables-list再满足–regex,如下只会dump表z1

mydumper -h 127.0.0.1 -u root --regex=test.z1 --outputdir=. --rows=10000 -v 3 -e --tables-list=z2,z1
** Message: Thread 1 dumping data for `test`.`z1`
** Message: Thread 2 dumping schema for `test`.`z1`

–rows的使用,设置–rows可以把一个表分成多个文件。分块的原则并不是根据–rows设定的行数来决定生成文件里包含的函数,而是通过rows和表的总行数计算出要生成的文件个数,尽量保证每个文件的大小一致。

表的总行数是如何获得的?
首先mydumper会选择一个索引,顺序是pk、uk或者show index from table里Cardinality最高的一个索引,再通过explain select index from table的rows字段获得总行数total_nums(可能不准确),于是第一个文件就是从select * from table where index >=1 and index < total_nums/ (int(total_nums/ rows) – 1) + 1。每个分块可以分到不同的线程,所以即便同一个表dump都可以很快加速。

ps:这个项目大量使用glib(gnome)比较少见,看了一下glib doc觉得glib设计的挺好的用起来很方便,否则实现一个消息队列加多线程还是要几百行代码的。接下来要看mydumper0.50的代码。

mydumper主要参数:

host, -h 连接的mysql服务器 
–user, -u 用户备份的连接用户
–password, -p
–port, -P 连接端口
–socket, -S 连接socket文件
–database, -B 需要备份的数据库
–table-list, -T 需要备份的表,用,分隔
–outputdir, -o 输出的目录 
–build-empty-files ,-e 如果表数据是空,还是产生一个空文件,默认无数据则只有表结构文件 
–regex, -x 支持正则表达式,如mydumper –regex ’^(?!(mysql|test))’
–ignore-engines, -i 忽略的存储引擎
–no-schemas, -m 不导出表结构 
–long-query-guard 长查询,默认60s,超过则通过mydumper
–kill-long-queries, -k 可以设置kill长查询
–verbose, -v 0 = silent, 1 = errors, 2 = warnings, 3 = info,默认是2
–binlogs, -b 导出binlog
–daemon, -D 启用守护进程模式 
–snapshot-interval, -I dump快照间隔时间,默认60s 
–logfile, -L mysqldumper日志输出,一般在Daemon模式下使用
myloader 大多参数和mydumper一样
–directory, -d 要还原的数据目录
–overwrite-tables, -o Drop any existing tables when restoring schemas

mydumper原理4的更多相关文章

  1. mydumper原理5

    前言 之前介绍了Oracle官方的多线程逻辑导入导出工具mysqlpump,但已经操作过的同学会发现其多线程的单位还是表,换句话说, 单表依然是 单线程导出 .网易早已使用mydumper/myloa ...

  2. MySQL 逻辑备份mysqldump&mysqlpump&mydumper原理解析

    目录 准备 mysqldump备份 mysqlpump备份 mydumper备份 想弄清除逻辑备份的原理,最好的办法是开启general_log,一探究竟 准备 创建用户 CREATE USER IF ...

  3. mydumper原理3

    Mydumper介绍 Mydumper是一个针对MySQL和Drizzle的高性能多线程备份和恢复工具.开发人员主要来自MySQL,Facebook,SkySQL公司.目前已经在一些线上使用了Mydu ...

  4. mydumper原理1

    http://www.cnblogs.com/linuxnote/p/3817698.html?utm_source=tuicool&utm_medium=referral mydumper介 ...

  5. mydumper原理2

    使用mydumper备份发生Waiting for table flush,导致所有线程都无法读和写 版本 mydumper 0.9.1OS centos6.6 X86_64mysql 5.6.25- ...

  6. mydumper原理介绍

      mydumper的安装:http://www.cnblogs.com/lizhi221/p/7010174.html   mydumper介绍   MySQL自身的mysqldump工具支持单线程 ...

  7. mysql备份工具 :mysqldump mydumper Xtrabackup 原理

    备份是数据安全的最后一道防线,对于任何数据丢失的场景,备份虽然不一定能恢复百分之百的数据(取决于备份周期),但至少能将损失降到最低.衡量备份恢复有两个重要的指标:恢复点目标(RPO)和恢复时间目标(R ...

  8. mysqldump+mydumper+xtrabackup备份原理流程

    mysqldump备份原理 备份的基本流程如下: 1.调用FTWRL(flush tables with read lock),全局禁止读写 2.开启快照读,获取此时的快照(仅对innodb表起作用) ...

  9. MySQL备份原理详解

    备份是数据安全的最后一道防线,对于任何数据丢失的场景,备份虽然不一定能恢复百分之百的数据(取决于备份周期),但至少能将损失降到最低.衡量备份恢复有两个重要的指标:恢复点目标(RPO)和恢复时间目标(R ...

随机推荐

  1. bjfu1252 贪心

    题目意思是给出一些开区间,这些区间有的相交,有的不相交,问你能否选出一些区间,使这些区间之间都不相交,并且选出的区间数最大. 这是个典型的贪心问题了.按区间的结束位置排序,然后顺序地选取区间,只要当前 ...

  2. Loadrunner模拟Json请求

    一.loadrunner脚本创建 1.Insert - New step -选择Custom Request - web_custom_request 2.填入相应参数 3.生成脚本,并修改如下(参数 ...

  3. CSS选择器的兼容性

    CSS 1 CSS2.1 CSS3 :hover 在IE6中只有a元素可用.E:empty 貌似在webkit核心浏览器中有些小bug.如果这个bug依然存在,不太确定如何测试.IE6不支持.clas ...

  4. DIV+CSS常见问题:DIV如何设置一个像素高度?

    CSS如何控制DIV实现1像素高度呢?问题看起来很简单,但万恶的IE6会让你很麻烦,不过解决办法很多,本文将介绍最简单的一种:DIV{height:1px;line-height:1px;font-s ...

  5. 自学hadoop(三)

    1) 关于hadoop在eclipse插件.经过自己的摸爬滚打.总结一下三条.     a) 2.0或者0.23.0吧 google比较方便.其他的可以自己编译.(这个我不敢保证.我本地环境事2.1. ...

  6. 智能会议白板系统CodeMap

    4个人3个月,1个项目,47个工程->白板系统 白板部分: 识别部分: 望多指教.

  7. 【现代程序设计】【homework-05】

    这次作业的运行效果图: 新建了20个客户端线程,服务器相应开了20个线程接收客户端数据,每一秒输出每一轮的结果 这次作业用c#完成 利用 Socket 类实现了局域网中的客户端和服务器之间的通信 主要 ...

  8. HDU 5832 A water problem (带坑水题)

    A water problem 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5832 Description Two planets named H ...

  9. HDU 5665 Lucky (水题)

    Lucky 题目链接: http://acm.hust.edu.cn/vjudge/contest/123316#problem/G Description Chaos August likes to ...

  10. JSF 2 outputText example

    In JSF 2.0 web application, "h:outputText" tag is the most common used tag to display plai ...