mydumper使用及原理浅析

来源:这里教程网 时间:2026-03-01 15:24:00 作者:

安装

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:  
        
Logmysql57-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(
36NOT 
NULL 
COMMENT 
'uuid of the source where the transaction was originally executed.',  
  
`interval_start` 
bigint(
20NOT 
NULL 
COMMENT 
'First number of interval.',  
  
`interval_end` 
bigint(
20NOT 
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 
    tablesUNLOCK 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/

  • 相关推荐