Skip to content

mydumper

mydumper是一个针对MySQL和Drizzle的高性能多线程备份和恢复工具,由MySQL、Facebook和SkySQL公司的开发人员共同开发。作为mysqldump的增强替代品,mydumper通过并行处理机制大幅提升了备份效率,在处理速度方面通常比传统mysqldump快10倍。

核心特性

  1. 多线程备份:支持并行导出多个表,显著提高备份速度
  2. 一致性快照:对事务性和非事务性表提供一致的快照(适用于0.2.2以上版本)
  3. 文件压缩:支持快速的文件压缩,减少存储空间占用
  4. 灵活的备份策略:支持正则匹配备份、分组和自检等功能
  5. 多线程恢复:支持并行数据加载(适用于0.2.1以上版本)
  6. 守护进程模式:支持定时快照和连续二进制日志备份(适用于0.5.0以上版本)
  7. 文件分片:支持将大表备份文件按行数或大小分片
  8. 元数据记录:自动记录备份时的二进制日志位置,便于点时间恢复

工作原理

mydumper的工作流程

  1. 连接目标数据库:建立与MySQL服务器的连接
  2. 检查长查询:通过show processlist判断是否有长查询,根据long-query-guardkill-long-queries参数决定退出或杀掉长查询
  3. 锁定表
    • 对MyISAM表施加FLUSH TABLES WITH READ LOCK(FTWRL),会阻塞DML语句
    • 对InnoDB表开启事务:START TRANSACTION WITH CONSISTENT SNAPSHOT
  4. 创建worker线程:默认创建4个工作线程
  5. 确定候选表:根据表类型分别插入innodb_tablenon_innodb_table以及table_schemas链表(表结构)
  6. 任务分配:将候选表通过任务队列分配给worker线程执行数据导出
  7. 释放锁:处理完MyISAM表后立即执行UNLOCK TABLES,减少锁定时间
  8. 等待完成:等待所有worker线程退出

减少锁等待模式(--less-locking)

mydumper提供了--less-locking参数来减少对InnoDB表的锁施加时间,其工作机制为:

  1. 主线程执行FLUSH TABLES WITH READ LOCK(全局锁)
  2. Dump线程执行START TRANSACTION WITH CONSISTENT SNAPSHOT
  3. LL Dump线程锁定非InnoDB表(线程内部锁)
  4. 主线程立即执行UNLOCK TABLES
  5. LL Dump线程导出非InnoDB表
  6. LL Dump线程解锁非InnoDB表
  7. Dump线程导出InnoDB表

这种模式显著减少了全局锁的持有时间,适合生产环境中使用。

备份文件结构

mydumper备份生成的文件结构如下:

tex
备份目录/
├── metadata                  # 元数据文件,记录备份时的binlog位置
├── database1.table1-schema.sql  # 表结构文件
├── database1.table1.sql       # 表数据文件
├── database1.table2-schema.sql
├── database1.table2.sql
└── ...

关键文件说明:

  1. metadata文件:记录了备份时间点的二进制日志文件名和位置,如果是在从库备份,还会记录主库的binlog信息
  2. 表结构文件:命名格式为database.table-schema.sql,包含表的DDL语句
  3. 表数据文件:命名格式为database.table.sql,包含表的数据插入语句
  4. 分片文件:当使用-r-F参数对表进行分片时,会生成多个数据文件如database.table.00000.sql

安装与配置

  1. 安装依赖包

    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++
  2. 下载并解压源码包

    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/
  3. 编译安装

    bash
    cmake .
    make
    make install
  4. 验证安装

    bash
    mydumper -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

注意事项

  1. 需要安装libmysqlclient-dev开发库才能编译安装mydumper
  2. 备份大表时建议使用-r选项分割文件
  3. 生产环境建议使用-e选项保证一致性
  4. 使用正则过滤时注意表达式语法
  5. 备份目录需要提前创建并有写权限
  6. 恢复备份需使用配套的myloader工具
  7. 使用--no-locks选项可能影响备份一致性
  8. 密码在命令行中可见,建议使用配置文件或交互式输入

数据恢复

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 usernameMySQL用户名myloader -u root
-p passwordMySQL密码myloader -p secret
-P portMySQL端口myloader -P 3307
-h hostMySQL主机地址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不设置时区为UTCmyloader --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

注意事项

  1. 恢复前确保目标MySQL服务有足够的权限和存储空间
  2. 大表恢复建议增加--innodb-optimize-keys选项提高性能
  3. 使用-o选项会覆盖现有表,操作前建议备份
  4. 恢复过程中会临时禁用外键检查,完成后自动恢复
  5. 如果备份时使用了压缩(-c),恢复时也需要同样选项
  6. 建议在业务低峰期执行大数据量恢复
  7. 恢复完成后检查metadata文件中的原始字符集设置
  8. 并行线程数(-t)建议设置为CPU核心数的2-4倍

常见问题解决

  1. 安装后无法运行

    • 报错:mydumper: error while loading shared libraries
    • 解决:将mydumper库路径添加到LD_LIBRARY_PATH/etc/ld.so.conf
  2. 高版本MySQL语法不兼容

    • 报错:SET OPTION SQL_QUOTE_SHOW_CREATE1语法错误
    • 解决:使用高版本mydumper或手动修改源码
  3. 备份被长查询阻塞

    • 现象:备份长时间不完成
    • 解决:设置--long-query-guard--kill-long-queries参数
  4. 内存不足

    • 现象:备份过程中被OOM killer终止
    • 解决:减少线程数或增加服务器内存