ITPub博客

首页 > 数据库 > MySQL > mydumper使用及原理浅析

mydumper使用及原理浅析

原创 MySQL 作者:神谕丶 时间:2020-10-07 14:36:19 0 删除 编辑

安装

yum 
install -y glib2-devel mysql-devel zlib-devel pcre-devel openssl-devel cmake gcc gcc-c++  

git  clone https://github.com/maxbube/mydumper  
cd mydumper  
cmake .  
make && make  install  

备份

用法十分简单,如需要做 全实例备份:


mydumper -u 
$user -p 
$password -h 
$host -G -E -R -c -o /data/backup --less-locking   

使用的时候,需要隔开选项和对应的值,比如-uroot要写成-u root,否则会报错


option parsing failed: 
Error parsing 
option -r, 
try --help  

-u -p -S/-h 这个肯定要指定,含义和 mysqldump、 mysql、 mysqladmin等工具一致


-B 指定数据库 (如果没有-B,默认就是全库表)  

-G 备份trigger  
-E 备份event  
-R 备份routine  
-c 压缩(gzip)  
-x 正则,比如备份多个指定的库:-x 'test|mysql',比如指定某些库不参与备份:-x '^(?!(sys|mysql))'   
-T 指定表,如-T test.tb1  
-t 线程数,默认4  
-l 设置长查询的阈值  
-K 加上这个参数,会考虑-l指定的时间,如果超过这个阈值,会将阻塞备份进程的会话干掉  
--less-locking 减少InnoDB表的锁时间  
--trx-consistency-only 代表本次备份只对事务表做一致性保证  
--skip-tz-utc 不加的话,会在dump的时候加上SET TIME_ZONE='+00:00'  


如果想看dump时详细的信息输出,可以指定 --verbose=3,日志级别为 info,默认不指定,为 warning(2)  

备份输出格式及内容

metadata记录的内容,基本上等同于 mysqldump的 --master-data和 --set-gtid-purged  

# 
cat 
metadata   

Started  dump  at: 2019 -03-25 16 :23:48  
SHOW  MASTER  STATUS:  
         Log:  mysql57-bin .000012  
         Pos: 749818446  
         GTID :ba5fdbe3-4949-11e8-8d33-525400652955:1-2  

Finished  dump  at: 2019 -03-25 16 :24:04  

*-schema.sql.gz为表结构


# zcat mysql.gtid_executed-schema.sql.gz  

/*!40101 SET NAMES binary*/;  
/*!40014 SET FOREIGN_KEY_CHECKS=0*/;  
/*!40103 SET TIME_ZONE='+00:00' */;  
CREATE  TABLE  `gtid_executed` (  
   `source_uuid`  char( 36)  NOT  NULL  COMMENT  'uuid of the source where the transaction was originally executed.',  
   `interval_start`  bigint( 20)  NOT  NULL  COMMENT  'First number of interval.',  
   `interval_end`  bigint( 20)  NOT  NULL  COMMENT  'Last number of interval.',  
  PRIMARY  KEY ( `source_uuid`, `interval_start`)  
)  ENGINE= InnoDB  DEFAULT  CHARSET=latin1 STATS_PERSISTENT= 0;  

.sql.gz为表数据


# zcat mysql.gtid_executed.sql.gz | head -5  

/*!40101 SET NAMES binary*/;  
/*!40014 SET FOREIGN_KEY_CHECKS=0*/;  
/*!40103 SET TIME_ZONE='+00:00' */;  
INSERT  INTO  `gtid_executed`  VALUES  
( "ba5fdbe3-4949-11e8-8d33-525400652955", 1, 2);  

在加了-B或者默认全库备份的场景下,还会有一个创建schema的文件:


# zcat mysql-schema-create.sql.gz  

CREATE  DATABASE  `mysql`  /*!40100 DEFAULT CHARACTER SET latin1 */;  

恢复

myloader -u 
$user -p 
$password -h 
$host -d /data/backup/  

常用可选参数:


-e,加了-e之后,导入的时候会记录binlog  

-t 同样是线程数,这个默认也是4  

备份和恢复速度

这个没测了。  
同事测了,反正就是快。(当然没 xtrabackup快)

原理

老规矩,策略是用 general_log分析一下:


SET 
GLOBAL general_log=
ON;  

SET  GLOBAL log_output= 'TABLE';  
TRUNCATE  TABLE mysql.general_log;  

再在备份的时候开启 --verbose=3,为了简明,我去掉了-G -E -R,意思是不备份 trigger、event、routine,且dump线程指定为2个。

测试库为test,表为a_myisam(MyISAM)、b_myisam(MyISAM)、t_1(InnoDB)、t_db_backup(InnoDB)

原理分析,主要是围绕加与不加 --trx-consistency-only和 --less-locking,并且为了了解如何并行dump,和对存在非事务引擎时,如何拿到逻辑一致性的备份。

先分析过程, 如果不想细看可以直接拉到底看结论 :

① 不加--less-locking:

测试命令:

mydumper -u 
$user -p 
$password -h 
$host -c -o /data/backup/ --verbose=3 -B 
test -t 2   

根据 mysql.general_log的 thread_id和 argument一起分析一下:


SELECT thread_id, command_type, 
left(argument,
80) 

FROM mysql.general_log;


跑上述sql,可以拉到如下结果:

① 可以看到,主线程374,先把 wait_timeout和 net_write_timeout给调大,然后跑个其他备份工具都爱加的全局读锁: FTWRL,成功后,再来个 START TRANSACTION /*!40108 WITH CONSISTENT SNAPSHOT */,保证是一致性读,接下来看 master status,记录下 log_file和 log_pos,如果为slave,也拉了slave的信息(此处未测slave的环境)

② 然后此处我指定的 -t 2,意思是分两个dump线程来备份,此处可以看到375和376连上来了:同样先调大 timeout两个参数,并先将隔离级别改为RR,无论关引擎,因现在还没开始判断表引擎。

③ 主线程374开始判断表引擎, SHOW TABLE STATUS,这样可以告诉dump线程,哪些是非事务引擎,因为需要在 FTWRL的情况下先备份

④ 两个dump线程开始备份非事务引擎,此处是 a_myisam和 b_myisam,直至备份结束。

④ 主线程374开始 unlock tables,之后,业务可写。同时,接下来的事情也和主线程没关系了,quit退出。

⑤ 两个dump线程继续备份剩余的事务表

这样,多个线程并行dump时,所读到的内容在时间上是一致性的。

虽然这样备份,备份是一致性的,但如果非事务引擎的表很多且很大,这样备份,会不会有点不妥?要等非事务引擎备份完,才可 UNLOCK TABLES然后dump事务表。
然后, mydumper就多了这样一个参数 --less-locking(mydumper 0.6.x后支持)

② 加上--less-locking:

测试命令:

mydumper -u 
$user -p 
$password -h 
$host -c -o /data/backup/ --verbose=3 -B 
test -t 2 --less-locking


同样,看一下general log输出

可以很明显发现,虽然指定了dump并发数为2,但是总共有5个线程。
翻了下percona的博客,发现 --less-locking的选项的加入,为每个 dump thread,多分配了一个 LL dump thread(即 less-locking dump thread)。

那么整个过程就变成了:  
① 主线程377依然先调两个 timeout参数,然后申请全局读锁 FTWRL,并开启一个事务,记录file和pos点,这一步与不加 --less-locking一致

② less-lokcing dump线程378、379连上来,设置 timeout,并等待主线程push非事务表到队列中。(这里就不需要开事务了,因为LL dump线程是负责非事务引擎的)

③ dump线程380、381连上来,设置 timeout,改隔离级别为RR,开启事务,并等待主线程分配事务表(380和381则只负责事务表)

④ 主线程377开始通过 SHOW TABLE STATUS判断非事务表和事务表

⑤ less-locking dump线程378、379拿到了两张非事务表的任务,开始 单独地拿两张非事务表的锁,每个线程一个拿到后,就可以开始备份非事务引擎了。

⑥ 因为非事务引擎表被单独的less-locking dump线程拿到了锁,对于主线程377,可以执行 UNLOCK TABLES了,这时,全局读锁 FTWRL被释放,整个过程就减少了事务表的锁时间。

⑦ 开始备份剩下没备份的事务表,直至退出

引入less-locking dump线程,不仅依然可以拿到非事务引擎和事务引擎混合的一致性备份,也可以减少对事务引擎锁的时间。
实际上,②和③顺序也是可以调换的(应该是并行的),在mydumper跑备份的时候,输出里stdout可以体现,节选如下:

…………

**  Message: Thread  3 connected using MySQL connection ID  378
**  Message: Thread  4 connected using MySQL connection ID  379
**  Message: Thread  1 connected using MySQL connection ID  380
**  Message: Thread  2 connected using MySQL connection ID  381
**  Message: Thread  4 dumping data  for `test`.`b_myisam`
**  Message: Thread  3 dumping data  for `test`.`a_myisam`
…………

③ 加--trx-consistency-only,(此处加不加--less-locking,过程和结果是一样的)

首先看一下这个参数是什么个意思:

WARNING **: 
Using trx_consistency_only, binlog coordinates will 
not be accurate 
if you are 

writing  to non transactional tables.

那么实际上和隔壁的 --single-transaction的效果是一样的——只管事务表,如果在备份过程中对非事务表有写操作,那binlog位置点不准。

所以,加不加 --less-locking就无所谓了,因为不对非事务引擎负责,过程均一致,大致如下:

这种情况,如果有非事务表,且存在写入的情况下,备份就不是一致性的了,整个过程十分简单:

① 主线程调两个 timeout参数,然后依然申请全局读锁 FTWRL,再开启事务,记录file和pos点

② dump线程389、390开事务

③ 主线程释放全局读锁并退出,此处还特意说明了 trx-only

④ dump线程开始备份

总结

  • 不加--less-locking:

① 主线程:FTWRL;

② dump线程: START  TRANSACTION  WITH  CONSISTENT  SNAPSHOT; dump non-InnoDB tables;
③ 主线程: UNLOCK  TABLES;
④ dump线程:dump InnoDB tables;
  • 加--less-locking:

① 主线程:FTWRL;

② dump线程: START  TRANSACTION  WITH  CONSISTENT  SNAPSHOT;
③ LL dump线程: LOCK  TABLES non- InnoDB;
④ 主线程: UNLOCK  TABLES
⑤ LL dump线程:dump non- InnoDB  tables;  UNLOCK non- INNODB;
⑥ dump线程:dump InnoDB tables;

平时用的话,似乎也可以不用判断是否有非事务引擎(当然最好不要用!),直接less-locking应该就能够满足需求了,日志级别我习惯设置为info。

对TokuDB似乎是可以支持的,但以前粗浅测过,且没细看。好像仍是拿不到一致性点的情况,这一点后续待校验。

mydumper -u 
$user -p 
$password -h 
$host -G -E -R -c --less-locking -o /data/backup/ \ 

--verbose=3 -B  test -t 8 -L /tmp/mydumper_`date +%Y%m%d%H%M%S`. log

其他

mydumper版本:0.9.5
MySQL版本:5.7.21

参考文档

mydumper-less-locking:

https://www.percona.com/blog/2014/06/13/mydumper-less-locking/



来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29773961/viewspace-2725573/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
微信公众号:神谕的暗影长廊

注册时间:2014-07-28

  • 博文量
    161
  • 访问量
    1194939