mydumper
mydumper是一个针对MySQL和Drizzle的高性能多线程备份和恢复工具,由MySQL、Facebook和SkySQL公司的开发人员共同开发。作为mysqldump的增强替代品,mydumper通过并行处理机制大幅提升了备份效率,在处理速度方面通常比传统mysqldump快10倍。
核心特性
- 多线程备份:支持并行导出多个表,显著提高备份速度
- 一致性快照:对事务性和非事务性表提供一致的快照(适用于0.2.2以上版本)
- 文件压缩:支持快速的文件压缩,减少存储空间占用
- 灵活的备份策略:支持正则匹配备份、分组和自检等功能
- 多线程恢复:支持并行数据加载(适用于0.2.1以上版本)
- 守护进程模式:支持定时快照和连续二进制日志备份(适用于0.5.0以上版本)
- 文件分片:支持将大表备份文件按行数或大小分片
- 元数据记录:自动记录备份时的二进制日志位置,便于点时间恢复
工作原理
mydumper的工作流程
- 连接目标数据库:建立与MySQL服务器的连接
- 检查长查询:通过
show processlist判断是否有长查询,根据long-query-guard和kill-long-queries参数决定退出或杀掉长查询 - 锁定表:
- 对MyISAM表施加
FLUSH TABLES WITH READ LOCK(FTWRL),会阻塞DML语句 - 对InnoDB表开启事务:
START TRANSACTION WITH CONSISTENT SNAPSHOT
- 对MyISAM表施加
- 创建worker线程:默认创建4个工作线程
- 确定候选表:根据表类型分别插入
innodb_table、non_innodb_table以及table_schemas链表(表结构) - 任务分配:将候选表通过任务队列分配给worker线程执行数据导出
- 释放锁:处理完MyISAM表后立即执行
UNLOCK TABLES,减少锁定时间 - 等待完成:等待所有worker线程退出
减少锁等待模式(--less-locking)
mydumper提供了--less-locking参数来减少对InnoDB表的锁施加时间,其工作机制为:
- 主线程执行
FLUSH TABLES WITH READ LOCK(全局锁) - Dump线程执行
START TRANSACTION WITH CONSISTENT SNAPSHOT - LL Dump线程锁定非InnoDB表(线程内部锁)
- 主线程立即执行
UNLOCK TABLES - LL Dump线程导出非InnoDB表
- LL Dump线程解锁非InnoDB表
- Dump线程导出InnoDB表
这种模式显著减少了全局锁的持有时间,适合生产环境中使用。
备份文件结构
mydumper备份生成的文件结构如下:
tex
备份目录/
├── metadata # 元数据文件,记录备份时的binlog位置
├── database1.table1-schema.sql # 表结构文件
├── database1.table1.sql # 表数据文件
├── database1.table2-schema.sql
├── database1.table2.sql
└── ...关键文件说明:
- metadata文件:记录了备份时间点的二进制日志文件名和位置,如果是在从库备份,还会记录主库的binlog信息
- 表结构文件:命名格式为
database.table-schema.sql,包含表的DDL语句 - 表数据文件:命名格式为
database.table.sql,包含表的数据插入语句 - 分片文件:当使用
-r或-F参数对表进行分片时,会生成多个数据文件如database.table.00000.sql
安装与配置
安装依赖包
bash# CentOS/RHEL yum install glib2-devel mysql-devel zlib-devel pcre-devel openssl-devel cmake make gcc-c++ git # Ubuntu/Debian apt-get install cmake make libglib2.0-dev libmysqlclient-dev zlib1g-dev libpcre3-dev g++下载并解压源码包
bash# Github地址:https://github.com/maxbube/mydumper wget https://launchpadlibrarian.net/225370879/mydumper-0.9.1.tar.gz tar xzvf mydumper-0.9.1.tar.gz cd mydumper-0.9.1/编译安装
bashcmake . make make install验证安装
bashmydumper -V myloader -V
安装完成后会在/usr/local/bin目录下生成两个可执行文件:mydumper(用于备份)和myloader(用于恢复)。
数据备份
基本语法
bash
mydumper [OPTION...] multi-threaded MySQL dumping选项
经典案例
bash
# 备份单个数据库
mydumper -u root -p password -B sakila -o /backup/sakila -t 8
# 备份所有数据库(排除information_schema和performance_schema)
mydumper -u root -p password -o /backup/full -t 8
#备份特定表
mydumper -u root -p password -B sakila -T actor,film -o /backup/tables
# 使用正则表达式备份匹配的表
mydumper -u root -p password -B sakila --regex '^sakila.(actor|film)' -o /backup/regex
# 压缩备份
mydumper -u root -p password -B sakila -c -o /backup/compressed
# 不备份表结构
mydumper -u root -p password -B sakila -m -o /backup/data_only
# 守护进程模式(持续备份)
mydumper -u root -p password -D -I 300 -L /var/log/mydumper.log -o /backup/daemon
# 减少锁等待
mydumper -u root -p password --less-locking -B sakila -o /backup/less_locking
# 完整备份testdb数据库到/backups目录,使用8线程
mydumper -B testdb -u root -p password -h 127.0.0.1 -P 3306 -t 8 -o /backups/testdb_backup -c -e -v 3
# 只备份以'log_'开头的表,分割为10万行一个文件
mydumper -B testdb -x '^log_' -r 100000 -o /backups/log_tables
# 仅备份表结构不备份数据
mydumper -B testdb -m -o /backups/schema_only
# 备份特定表并忽略长查询
mydumper -B testdb -T users,orders --long-query-guard 30 --kill-long-queries -o /backups/important_tables注意事项
- 需要安装
libmysqlclient-dev开发库才能编译安装mydumper - 备份大表时建议使用
-r选项分割文件 - 生产环境建议使用
-e选项保证一致性 - 使用正则过滤时注意表达式语法
- 备份目录需要提前创建并有写权限
- 恢复备份需使用配套的
myloader工具 - 使用
--no-locks选项可能影响备份一致性 - 密码在命令行中可见,建议使用配置文件或交互式输入
数据恢复
mydumper的配套工具myloader用于恢复备份数据,支持多线程恢复。
基本语法
bash
myloader [OPTION...] multi-threaded MySQL loader选项
| 选项 | 描述 | 示例 |
|---|---|---|
-d directory | 备份文件所在目录 | myloader -d /backups/ |
-q | 静默模式(减少输出) | myloader -q |
-o | 覆盖已存在的表 | myloader -o |
-B database | 恢复到指定数据库 | myloader -B newdb |
-s | 只恢复表结构 | myloader -s |
-t threads | 使用的线程数 | myloader -t 8 |
-u username | MySQL用户名 | myloader -u root |
-p password | MySQL密码 | myloader -p secret |
-P port | MySQL端口 | myloader -P 3307 |
-h host | MySQL主机地址 | myloader -h 192.168.1.100 |
-v verbose_level | 详细级别(0-2) | myloader -v 2 |
-e | 使用单个事务 | myloader -e |
-c | 压缩备份文件 | myloader -c |
-D | 启用调试模式 | myloader -D |
-x regex | 使用正则表达式匹配表 | myloader -x '^test.*' |
-k | 不删除临时文件 | myloader -k |
-r | 恢复前删除目标表 | myloader -r |
--innodb-optimize-keys | 导入期间禁用InnoDB键 | myloader --innodb-optimize-keys |
--skip-definer | 忽略DEFINER子句 | myloader --skip-definer |
--skip-tz-utc | 不设置时区为UTC | myloader --skip-tz-utc |
--enable-binlog | 启用二进制日志 | myloader --enable-binlog |
--set-names charset | 设置连接字符集 | myloader --set-names utf8mb4 |
--complete-insert | 使用完整INSERT语句 | myloader --complete-insert |
--ignore-duplicates | 忽略重复记录 | myloader --ignore-duplicates |
--no-data | 同-s选项 | myloader --no-data |
--overwrite-tables | 同-o选项 | myloader --overwrite-tables |
--purge-mode | 同-r选项 | myloader --purge-mode |
--regex | 同-x选项 | myloader --regex '^test.*' |
--skip-triggers | 跳过触发器导入 | myloader --skip-triggers |
--skip-post | 跳过恢复后优化 | myloader --skip-post |
恢复示例
bash
# 恢复整个数据库
myloader -u root -p password -d /backup/sakila -B sakila -t 8
# 恢复到不同数据库名
myloader -u root -p password -d /backup/sakila -B sakila_copy -o
# 完整恢复备份到原数据库(使用12线程)
myloader -d /backups/full_backup -u root -p password -h 127.0.0.1 -P 3306 -t 12 -v 2
# 恢复到新数据库并覆盖现有表
myloader -d /backups/full_backup -B newdb -o -u admin -p admin123
# 只恢复以'log_'开头的表(使用正则)
myloader -d /backups/full_backup -x '^log_' -t 4
# 只恢复表结构不恢复数据
myloader -d /backups/full_backup -s -u root -p password
# 处理压缩备份并启用二进制日志
myloader -d /backups/compressed_backup -c --enable-binlog -t 8
# 仅恢复表结构,先恢复schema文件
for f in /backup/sakila/*-schema.sql; do mysql -u root -p password < $f; done注意事项
- 恢复前确保目标MySQL服务有足够的权限和存储空间
- 大表恢复建议增加
--innodb-optimize-keys选项提高性能 - 使用
-o选项会覆盖现有表,操作前建议备份 - 恢复过程中会临时禁用外键检查,完成后自动恢复
- 如果备份时使用了压缩(
-c),恢复时也需要同样选项 - 建议在业务低峰期执行大数据量恢复
- 恢复完成后检查
metadata文件中的原始字符集设置 - 并行线程数(
-t)建议设置为CPU核心数的2-4倍
常见问题解决
安装后无法运行:
- 报错:
mydumper: error while loading shared libraries - 解决:将mydumper库路径添加到
LD_LIBRARY_PATH或/etc/ld.so.conf
- 报错:
高版本MySQL语法不兼容:
- 报错:
SET OPTION SQL_QUOTE_SHOW_CREATE1语法错误 - 解决:使用高版本mydumper或手动修改源码
- 报错:
备份被长查询阻塞:
- 现象:备份长时间不完成
- 解决:设置
--long-query-guard和--kill-long-queries参数
内存不足:
- 现象:备份过程中被OOM killer终止
- 解决:减少线程数或增加服务器内存
