mysqldump 是单线程进行数据库备份的工具,在数据量比较大时,备份速度下降十分严重,mydumper 支持并行备份,备份速度更快,备份耗费时间更少。
特性:
MySQL
逻辑导入导出工具mydumper
备份机制mydumper
备份原理示意图time | master_thread | worker_thread |
---|---|---|
t1 | FLUSH TABLES WITH READ LOCK | |
t2 | START TRANSACTION /*!40108 WITH CONSISTENT SNAPSHOT */ | |
t3 | SHOW MASTER STATUS | |
t4 | SHOW SLAVE STATUS | |
t5 | Connect db_instance using TCP/IP | |
t6 | SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ | |
t7 | START TRANSACTION /*!40108 WITH CONSISTENT SNAPSHOT */ | |
t8 | SHOW DATABASES | |
t9 | Init DB | |
t10 | backup all tables of myisam and some innodb tables | |
t11 | UNLOCK TABLES /* FTWRL */ | |
t12 | Quit | |
t13 | backup innodb tables | |
t14 | Quit |
mydumper
备份过程mydumper 备份期间 general log
15180 Connect root@127.0.0.1 on db3 using TCP/IP
15180 Query FLUSH TABLES WITH READ LOCK
15180 Query START TRANSACTION /*!40108 WITH CONSISTENT SNAPSHOT */
15180 Query SHOW MASTER STATUS
15180 Query SHOW SLAVE STATUS
15181 Connect root@127.0.0.1 on using TCP/IP
15181 Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
15181 Query START TRANSACTION /*!40108 WITH CONSISTENT SNAPSHOT */
15182 Connect root@127.0.0.1 on using TCP/IP
15182 Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
15182 Query START TRANSACTION /*!40108 WITH CONSISTENT SNAPSHOT */
15183 Connect root@127.0.0.1 on using TCP/IP
15183 Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
15183 Query START TRANSACTION /*!40108 WITH CONSISTENT SNAPSHOT */
15184 Connect root@127.0.0.1 on using TCP/IP
15184 Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
15184 Query START TRANSACTION /*!40108 WITH CONSISTENT SNAPSHOT */
15181 Init DB db3
15182 Query SHOW CREATE DATABASE `db3`
15181 Query SHOW TABLE STATUS
15182 Query select COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='db3' and TABLE_NAME='t_myisam' and extra like '%GENERATED%'
15184 Query select COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='db3' and TABLE_NAME='t2' and extra like '%GENERATED%'
15181 Query select COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='db3' and TABLE_NAME='t3' and extra like '%GENERATED%'
15183 Query select COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='db3' and TABLE_NAME='t1' and extra like '%GENERATED%'
15184 Query SELECT /*!40001 SQL_NO_CACHE */ * FROM `db3`.`t2`
15181 Query SELECT /*!40001 SQL_NO_CACHE */ * FROM `db3`.`t3`
15182 Query SELECT /*!40001 SQL_NO_CACHE */ * FROM `db3`.`t_myisam`
15184 Query select COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='db3' and TABLE_NAME='t5' and extra like '%GENERATED%'
15181 Query select COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='db3' and TABLE_NAME='t4' and extra like '%GENERATED%'
15183 Query SELECT /*!40001 SQL_NO_CACHE */ * FROM `db3`.`t1`
15180 Query UNLOCK TABLES /* FTWRL */
15182 Query SHOW CREATE TABLE `db3`.`t1`
15184 Query SELECT /*!40001 SQL_NO_CACHE */ * FROM `db3`.`t5`
15183 Query SHOW CREATE TABLE `db3`.`t2`
15180 Quit
15184 Query SHOW CREATE TABLE `db3`.`t3`
15183 Query SHOW CREATE TABLE `db3`.`t4`
15181 Query SELECT /*!40001 SQL_NO_CACHE */ * FROM `db3`.`t4`
15183 Query SHOW CREATE TABLE `db3`.`t_myisam`
15184 Quit
15181 Quit
15183 Quit
15182 Query SHOW CREATE TABLE `db3`.`t5`
15182 Quit
mydumper 备份过程分析
15180
先执行 FLUSH TABLES WITH READ LOCK
,施加全局只读锁,使实例处于相对静止状态,以阻止DML
语句写入,保证数据的一致性15180
开启事务一致性快照,读取当前实例的二逬制日志文件名和日志的写入位置,并写入metadata
文件,以供即使点恢复使用。如果是在从库上使用 mydumper
进行备份,则还会记录备份时同步至主库的二进制日志文件及写入位置N
个(线程数可以指定,默认是4
) dump
线程,如 15181
,每初始化出一个线程,就将该会话的隔离级别设置为 RR
,并开启快照事务dump non-InnoDB tables
,首先导出全部非事务引擎表(在 ftwrl
期间也备份一些 innodb
表)15180
执行 UNLOCK TABLES
, 所有非事务引擎表备份完后,释放全局只读锁 ;dump InnoDB tables
,基于事务导出 InnoDB
表dump
线程各自退出,事务自动回滚一共有 4 种文件
metadata
db_name-schema-create.sql
db_name.tb_name-schema.sql
db_name.tb_name.sql
记录了备份数据库在备份时间点的二进制日志文件名,日志的写入位置,如果是在从库进行备份,还会记录备份时同步至主库的二进制日志文件及写入位置
数据库定义文件
#cat db3-schema-create.sql
CREATE DATABASE `db3` /*!40100 DEFAULT CHARACTER SET utf8 */;
表结构定义文件
#cat db3.t1-schema.sql
/*!40101 SET NAMES binary*/;
/*!40014 SET FOREIGN_KEY_CHECKS=0*/;
/*!40103 SET TIME_ZONE='+00:00' */;
CREATE TABLE `t1` (
`id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
表数据文件
#cat db3.t1.sql
/*!40101 SET NAMES binary*/;
/*!40014 SET FOREIGN_KEY_CHECKS=0*/;
/*!40103 SET TIME_ZONE='+00:00' */;
INSERT INTO `t1` VALUES
(1),
(2),
(3),
(4),
(5);
如果对表文件分片,将生成多个备份数据文件,可以指定行数或指定大小分片
#ll
total 448740
-rw-r--r-- 1 root root 145 May 24 15:43 metadata.partial
-rw-r--r-- 1 root root 22223199 May 24 15:43 zst.sbtest10.00000.sql
-rw-r--r-- 1 root root 22334304 May 24 15:43 zst.sbtest10.00001.sql
-rw-r--r-- 1 root root 22334304 May 24 15:43 zst.sbtest10.00002.sql
-rw-r--r-- 1 root root 22334304 May 24 15:43 zst.sbtest10.00003.sql
-rw-r--r-- 1 root root 22334304 May 24 15:43 zst.sbtest10.00004.sql
-rw-r--r-- 1 root root 22334304 May 24 15:43 zst.sbtest10.00005.sql
-rw-r--r-- 1 root root 22334304 May 24 15:43 zst.sbtest10.00006.sql
-rw-r--r-- 1 root root 22334304 May 24 15:43 zst.sbtest10.00007.sql
-rw-r--r-- 1 root root 22332697 May 24 15:43 zst.sbtest10.00008.sql
Centos
yum install glib2-devel mysql-devel zlib-devel pcre-devel cmake
git clone https://github.com/maxbube/mydumper.git
cd mydumper
cmake .
make
make install
mydumper -V
mydumper 0.10.0, built against MySQL 5.7.23
myloader -V
myloader 0.10.0, built against MySQL 5.7.23
mydumper主要有以下两个命令:mydumper用于备份,myloader用于恢复。
在备份数据时,默认只备份库、表的定义和数据文件,触发器,事件,函数和存储过程需要加上相应的选项才会备份
Usage:
mydumper [OPTION?] multi-threaded MySQL dumping
Help Options:
-?, --help Show help options
Application Options:
-B, --database 要备份的数据库,不指定则备份所有库
-T, --tables-list 需要备份的表,多表用逗号隔开
-O, --omit-from-file 包含要跳过的 database.table 条目列表的文件,每行一个(在应用正则表达式选项之前跳过)
-o, --outputdir 备份文件输出的目录
-s, --statement-size 生成的 insert 语句的字节数,默认 1000000(这个参数不能太小,不然会报 Row bigger than statement_size for tools.t_serverinfo)
-r, --rows 将表按行分块时,指定的块行数,指定这个选项会关闭 --chunk-filesize
-F, --chunk-filesize 将表按大小分块时,指定的块大小,单位是 MB
-c, --compress 压缩输出文件
-e, --build-empty-files 如果表数据是空,还是产生一个空文件(默认无数据则只有表结构文件)
-x, --regex 支持正则表达式匹配'db.table',如mydumper –regex '^(?!(mysql|test))'
-i, --ignore-engines 忽略的存储引擎,用逗号分割
-N, --insert-ignore 使用 INSERT IGNORE 转储行数据
-m, --no-schemas 不备份表结构
-d, --no-data 不备份表数据
-G, --triggers 备份触发器
-E, --events 备份事件
-R, --routines 备份存储过程和函数
-W, --no-views 不备份视图
-k, --no-locks 不使用临时共享只读锁,使用这个选项会造成数据不一致
--no-backup-locks 不使用 Percona 备份锁
--less-locking 减少对 InnoDB 表的锁定时间
-l, --long-query-guard 设定阻塞备份的长查询超时时间,单位是秒,默认是60秒(超时后默认mydumper将会退出)
-K, --kill-long-queries 杀掉长查询 (而不是退出 mydumper)
-D, --daemon 启用守护进程模式,守护进程模式以某个间隔不间断对数据库进行备份
-I, --snapshot-interval 每个备份快照之间的间隔(以分钟为单位),需要 --daemon 选项,默认为 60
-L, --logfile 使用的日志文件名(mydumper所产生的日志), 默认使用标准输出
--tz-utc 设置时区,只有备份应用到不同时区时使用。默认使用 --skip-tz-utc 来关闭该选项
--skip-tz-utc 见上
--use-savepoints 使用 savepoints 来减少采集 metadata 所造成的锁时间,需要 SUPER 权限
--success-on-1146 Not increment error count and Warning instead of Critical in case of table doesn't exist
--lock-all-tables 锁住实例上所有表,而不是给实例施加 FTWRL
-U, --updated-since 使用 update_time 来备份最近 U 天内有过更新记录的表
--trx-consistency-only Transactional consistency only
--complete-insert 包含列名的完整 INSERT 语句
-z, --tidb-snapshot Snapshot to use for TiDB
-h, --host 连接的主机名
-u, --user 备份所使用的用户
-p, --password 密码(不支持交互式输入密码)
-a, --ask-password 提示用户密码
-P, --port 端口
-S, --socket 使用 socket 方式备份实例(使用不成功,暂时只成功的使用了基于 host 的方式备份)
-t, --threads 开启的备份线程数,默认是 4
-C, --compress-protocol 压缩与 mysql 通信的数据
-V, --version 显示版本号
-v, --verbose 输出信息模式, 0 = silent, 1 = errors, 2 = warnings, 3 = info, 默认为 2
--defaults-file 使用一个指定的文件
--ssl 使用 SSL 连接
--key The path name to the key file
--cert The path name to the certificate file
--ca The path name to the certificate authority file
--capath The path name to a directory that contains trusted SSL CA certificates in PEM format
--cipher A list of permissible ciphers to use for SSL encryption
Usage:
myloader [OPTION?] multi-threaded MySQL loader
Help Options:
-?, --help Show help options
Application Options:
-d, --directory 要导入的备份文件要存放的文件夹
-q, --queries-per-transaction 每个事务的query数量, 默认1000
-o, --overwrite-tables 如果表存在则先删除,使用该参数时,需要确保备份时候备份了表结构,不然还原会找不到表
-B, --database 指定需要还原的数据库
-s, --source-db 还原的数据库(备份文件中)
-e, --enable-binlog 启用还原数据的二进制日志
-h, --host 主机
-u, --user 还原的用户
-p, --password 密码
-a, --ask-password Prompt For User password
-P, --port TCP/IP 连接所用的端口号
-S, --socket UNIX socket 方式连接的文件
-t, --threads 还原所使用的线程数量
-C, --compress-protocol 在 MySQL 连接上使用压缩
-V, --version 显示版本
-v, --verbose 输出模式, 0 = silent, 1 = errors, 2 = warnings, 3 = info, 默认为2
可选参数
备份使用线程数
--threads
是否使用 savepoints,以减少 metalock 锁的时间,该选项与 --rows 冲突
--use-savepoints
长查询的时间,若查询超过该时间,则中断 mydumper
--long-query-guard
若有长查询,则杀掉该长查询
--kill-long-queries
压缩
--compress
mydumper -u root -p root -h 192.168.2.249 -P 3306 --threads 4 --use-savepoints --long-query-guard 300 --kill-long-queries --compress -o /backup/mysql/bak
mydumper -u root -p root -h 192.168.2.249 -P 3306 --threads 4 --rows 100000 --long-query-guard 300 --kill-long-queries --compress -o /backup/mysql/bak
mydumper -u root -p root -h 192.168.2.249 -P 3306 --threads 4 --chunk-filesize 100 --long-query-guard 300 --kill-long-queries --compress -o /backup/mysql/bak
注意
选项后面要加一个空格,否则会报错
mydumper -u root -p root -h 192.168.2.249 -P 3306 -B db3 -o /backup/mysql/db3_3306
不能通过像 mysqldump 那样以逗号分隔备份多个库,而是通过正则表达式来达到备份多个库的目的。
方法1
mydumper -u root -p root -h 192.168.2.249 -P 3306 --regex '^(db3\.|db2\.)' -o /backup/mysql/db3_db2_3306
方法2
mydumper -u root -p root -h 192.168.2.249 -P 3306 --regex 'db3|db2' -o /backup/mysql/db3_db2_3306
mydumper -u root -p root -h 192.168.2.249 -P 3306 -B db3 -T t1 -o /backup/mysql/bak
多表之间用逗号分隔 -T t1,t2
mydumper -u root -p root -h 192.168.2.249 -P 3306 -B db3 -T t1,t2 -o /backup/mysql/bak
只备份多个库下的几张表(要备份的表数量较少)
mydumper -u root -p root -h 192.168.2.249 -P 3306 --regex '^(db3\.t1|db3\.t2|db2\.b1|db2\.b2)' -o /backup/mysql/bak
备份多个库下的大部分表(不需要备份的表数量较少)
方法 1
mydumper -u root -p root -h 192.168.2.249 -P 3306 --regex '^(?!db3\.t1|db3\.t2|db2\.b1|db2\.b2)' -o /backup/mysql/bak
方法 2 : 通过 --omit-from-file 选项,排除掉不需要备份的表
> cat omit_db_table.txt
db3.t1
db3.t2
db2.b1
mydumper -u root -p root -h 192.168.2.249 -P 3306 -O omit_db_table.txt --regex '^(db3\.|db2\.)' -o /backup/mysql/bak2
单库
mydumper -u root -p root -h 192.168.2.249 -P 3306 -B db3 -m -o /backup/mysql/bak
多库
mydumper -u root -p root -h 192.168.2.249 -P 3306 --regex '^(db3\.|db2\.)' -m -o /backup/mysql/bak
单库
mydumper -u root -p root -h 192.168.2.249 -P 3306 -B db3 -d -o /backup/mysql/bak
多库
mydumper -u root -p root -h 192.168.2.249 -P 3306 --regex '^(db3\.|db2\.)' -d -o /backup/mysql/bak
mydumper -u root -p root -h 192.168.2.249 -P 3306 --threads 8 -o /backup/mysql/bak
使用 gzip 进行压缩,可选择压缩的级别为 1-9,compress faster - compress better
mydumper -u root -p root -h 192.168.2.249 -P 3306 -c 1 -o /backup/mysql/bak
mydumper -u root -p root -h 192.168.2.249 -P 3306 -B zst -r 100000 -o /backup/mysql/bak
mydumper -u root -p root -h 192.168.2.249 -P 3306 -B zst -F 100 -o /backup/mysql/bak
mydumper -u root -p root -h 192.168.2.249 -P 3306 -B zst --daemon -o /backup/mysql/bak
triggers,events,routines
对象的备份默认不备份 triggers,events,routines
,只备份库,表,数据。若想对这些对象进行备份,需要加上指定的选项
triggers
triggers
备份文件单独一个文件保存,格式为 db_name.tb_name-schema-triggers.sql
mydumper -u root -p root -h 192.168.2.249 -P 3306 --triggers --no-data -o /backup/mysql/bak
备份出来的文件目录
-rw-r--r-- 1 root root 189 May 29 11:11 db2.b2-schema.sql
-rw-r--r-- 1 root root 62 May 29 11:11 db2-schema-create.sql
-rw-r--r-- 1 root root 239 May 29 11:11 db3.account-schema.sql
-rw-r--r-- 1 root root 651 May 29 11:11 db3.account-schema-triggers.sql
-rw-r--r-- 1 root root 62 May 29 11:11 db3-schema-create.sql
-rw-r--r-- 1 root root 189 May 29 11:11 db3.t1-schema.sql
-rw-r--r-- 1 root root 1350 May 29 11:11 sys.sys_config-schema-triggers.sql
-rw-r--r-- 1 root root 185 May 29 11:11 metadata
触发器定义文件 db3.account-schema-triggers.sql 内容
#cat db3.account-schema-triggers.sql
SET @PREV_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT;
SET @PREV_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS;
SET @PREV_COLLATION_CONNECTION=@@COLLATION_CONNECTION;
SET character_set_client = utf8;
SET character_set_results = utf8;
SET collation_connection = utf8_general_ci;
CREATE DEFINER=`root`@`localhost` TRIGGER upd_check BEFORE UPDATE ON account
FOR EACH ROW
begin
IF NEW.amount < 0 THEN
SET NEW.amount = 0;
ELSEIF NEW.amount > 100 THEN
SET NEW.amount = 100;
end if;
end;
SET character_set_client = @PREV_CHARACTER_SET_CLIENT;
SET character_set_results = @PREV_CHARACTER_SET_RESULTS;
SET collation_connection = @PREV_COLLATION_CONNECTION;
删除除触发器定义文件之外的所有表结构定义文件
rm -f `ls | grep -v "triggers\.sql"`
删除后的目录内容
-rw-r--r-- 1 root root 651 May 29 11:11 db3.account-schema-triggers.sql
-rw-r--r-- 1 root root 1350 May 29 11:11 sys.sys_config-schema-triggers.sql
events
和 routines
events
和 routines
备份在同一个文件中,格式为 dbname-schema-post.sql
mydumper -u root -p root -h 192.168.2.249 -P 3306 --events --routines --no-data -B zst -o /backup/mysql/bak
目录内容
-rw-r--r-- 1 root root 380 May 29 11:16 zst.sbtest9-schema.sql
-rw-r--r-- 1 root root 62 May 29 11:16 zst-schema-create.sql
-rw-r--r-- 1 root root 1363 May 29 11:16 zst-schema-post.sql
-rw-r--r-- 1 root root 276 May 29 11:16 zst.t2-schema.sql
zst-schema-post.sql 文件的内容
#cat zst-schema-post.sql
SET @PREV_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT;
SET @PREV_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS;
SET @PREV_COLLATION_CONNECTION=@@COLLATION_CONNECTION;
SET character_set_client = utf8;
SET character_set_results = utf8;
SET collation_connection = utf8_general_ci;
DROP FUNCTION IF EXISTS `hello`;
CREATE DEFINER=`root`@`localhost` FUNCTION `hello`() RETURNS varchar(255) CHARSET utf8
BEGIN
RETURN 'Hello world,i am mysql';
END;
SET character_set_client = @PREV_CHARACTER_SET_CLIENT;
SET character_set_results = @PREV_CHARACTER_SET_RESULTS;
SET collation_connection = @PREV_COLLATION_CONNECTION;
SET @PREV_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT;
SET @PREV_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS;
SET @PREV_COLLATION_CONNECTION=@@COLLATION_CONNECTION;
SET character_set_client = utf8;
SET character_set_results = utf8;
SET collation_connection = utf8_general_ci;
DROP EVENT IF EXISTS `e_daily`;
CREATE DEFINER=`root`@`localhost` EVENT `e_daily` ON SCHEDULE EVERY 1 MINUTE STARTS '2019-05-28 17:31:58' ON COMPLETION NOT PRESERVE ENABLE COMMENT 'Saves total number of sessions then clears the table each day' DO begin
INSERT INTO t2 values (null,current_timestamp);
END;
SET character_set_client = @PREV_CHARACTER_SET_CLIENT;
SET character_set_results = @PREV_CHARACTER_SET_RESULTS;
SET collation_connection = @PREV_COLLATION_CONNECTION;
删除除 events
和 routines
外的定义文件
rm -f `ls | grep -v "post\.sql"`
mydumper 备份触发器、事件、函数和存储过程没有 mysqldump 那么清晰简单。
备份整个实例,包括触发器,事件,函数和存储过程
还原整个实例
myloader -u root -p root -S /tmp/mysql3307.sock -d /backup/mysql/bak/
master
mydumper -u root -p root -S /tmp/mysql3306.sock -G -R -E -o /backup/mysql/bak
slave
先升级 mysql,否则会报 mysql.event, mysql.proc 这些表不存在的错误
mysql_upgrade -u root -p root -S /tmp/mysql3307.sock -P 3307
还原 3306 实例上备份的数据到 3307 实例上, 3307 实例是初始化的,没有数据写入的实例
myloader -u root -p root -S /tmp/mysql3307.sock -d /backup/mysql/bak
注意事项
slave 上的 GTID 信息需要根据 metadata 文件进行手动更新,myloader 并没有自动更新 GTID 信息
slave
reset master;
set global gtid_purged = 'xxx';
从备份的单个库文件中还原单库
myloader -u root -p root -h 192.168.2.249 -P 3307 -B zst -d /backup/mysql/bak/
从备份的真个实例文件中还原单库
myloader -u root -p root -h 192.168.2.249 -P 3307 -B zst -s zst -d /backup/mysql/bak/
备份多个库
mydumper -u root -p root -h 192.168.2.249 -P 3306 --regex 'zst|db3' -o /backup/mysql/bak
还原多个库
myloader -u root -p root -h 192.168.2.249 -P 3307 -d /backup/mysql/bak/
备份单库多表
mydumper -u root -p root -h 192.168.2.249 -P 3306 -B zst -T sbtest1,sbtest2 -o /backup/mysql/bak
还原单库多表
myloader -u root -p root -h 192.168.2.249 -P 3307 -d /backup/mysql/bak/
当备份是实例级别的备份时,可以将需要的表的文件放到另一个目录中,还原时指定该目录即可
备份多个库
mydumper -u root -p root -h 192.168.2.249 -P 3306 --regex 'zst|db3' -o /backup/mysql/bak
还原多个库到一个库
myloader -u root -p root -h 192.168.2.249 -P 3307 -B zst -d /backup/mysql/bak/