Skip to content

MariaDB 增量恢复

增量恢复概述

增量恢复是指在全量备份的基础上,通过应用增量备份文件来恢复数据库到某个特定时间点的过程。增量恢复可以大幅减少备份存储需求和备份时间,同时保持较短的恢复时间。

增量恢复原理

增量恢复的核心原理是基于时间点的差异恢复:

  1. 首先恢复最近的全量备份
  2. 然后依次恢复全量备份之后创建的所有增量备份
  3. 最后应用二进制日志(可选)进行时间点恢复

增量恢复类型

恢复类型适用场景恢复速度数据完整性工具
物理增量恢复大规模数据库、快速恢复需求mariabackup
逻辑增量恢复小型数据库、单库/单表恢复自定义脚本+mysqldump

物理增量恢复(使用 mariabackup)

恢复准备

1. 停止 MariaDB 服务

bash
# 系统服务方式停止
systemctl stop mariadb

# 或使用 mysqld_safe 停止
mysqladmin -u root -p shutdown

2. 清理数据目录

bash
# 备份当前数据目录(可选)
mv /var/lib/mysql /var/lib/mysql_bak_$(date +%Y%m%d_%H%M%S)

# 创建新的数据目录
mkdir -p /var/lib/mysql

# 设置正确的权限
chown -R mysql:mysql /var/lib/mysql
chmod -R 700 /var/lib/mysql

3. 准备全量备份和增量备份文件

确保所有需要的备份文件都已准备就绪:

bash
# 检查全量备份和增量备份目录
ls -la /backup/mariadb/full/
ls -la /backup/mariadb/incremental/

如果备份文件是压缩的,需要先解压:

bash
# 解压全量备份
mariabackup --decompress \
  --target-dir=/backup/mariadb/full/20231227_120000 \
  --parallel=4

# 解压增量备份
mariabackup --decompress \
  --target-dir=/backup/mariadb/incremental/20231227_180000 \
  --parallel=4

mariabackup --decompress \
  --target-dir=/backup/mariadb/incremental/20231228_060000 \
  --parallel=4

执行增量恢复

增量恢复的关键步骤是将全量备份和所有增量备份合并成一个完整的备份,然后进行恢复。

1. 准备全量备份

bash
# 准备全量备份(--apply-log-only 表示不回滚未提交的事务)
mariabackup --prepare \
  --target-dir=/backup/mariadb/full/20231227_120000 \
  --apply-log-only \
  --parallel=4

2. 依次合并增量备份

按照增量备份的创建顺序,依次将增量备份合并到全量备份中:

bash
# 合并第一个增量备份(20231227_180000)
mariabackup --prepare \
  --target-dir=/backup/mariadb/full/20231227_120000 \
  --incremental-dir=/backup/mariadb/incremental/20231227_180000 \
  --apply-log-only \
  --parallel=4

# 合并第二个增量备份(20231228_060000)
mariabackup --prepare \
  --target-dir=/backup/mariadb/full/20231227_120000 \
  --incremental-dir=/backup/mariadb/incremental/20231228_060000 \
  --apply-log-only \
  --parallel=4

3. 完成备份准备(最后一次不需要 --apply-log-only)

bash
# 完成备份准备,回滚未提交的事务
mariabackup --prepare \
  --target-dir=/backup/mariadb/full/20231227_120000 \
  --parallel=4

4. 执行恢复操作

bash
# 使用 --copy-back 恢复
mariabackup --copy-back \
  --target-dir=/backup/mariadb/full/20231227_120000 \
  --datadir=/var/lib/mysql \
  --parallel=4

# 或使用 --move-back 恢复(更快,但会删除备份文件)
# mariabackup --move-back \
#   --target-dir=/backup/mariadb/full/20231227_120000 \
#   --datadir=/var/lib/mysql \
#   --parallel=4

恢复后处理

1. 检查数据目录权限

bash
# 确保数据目录权限正确
chown -R mysql:mysql /var/lib/mysql
chmod -R 700 /var/lib/mysql

2. 检查配置文件

bash
# 确保配置文件中的 datadir 指向正确的位置
grep datadir /etc/my.cnf

3. 启动 MariaDB 服务

bash
# 系统服务方式启动
systemctl start mariadb

# 或使用 mysqld_safe 启动
mysqld_safe --defaults-file=/etc/my.cnf &

4. 验证恢复结果

bash
# 检查服务状态
systemctl status mariadb

# 连接数据库并验证
mysql -u root -p -e "SHOW DATABASES;"
mysql -u root -p -e "SELECT COUNT(*) FROM mydatabase.mytable;"
mysql -u root -p -e "SELECT MAX(updated_at) FROM mydatabase.mytable;"  # 验证恢复到的时间点

不同场景下的增量恢复

场景1:主库崩溃,恢复到最新状态

  1. 停止主库服务

    bash
    systemctl stop mariadb
  2. 清理数据目录

    bash
    mv /var/lib/mysql /var/lib/mysql_bak
    mkdir -p /var/lib/mysql
    chown -R mysql:mysql /var/lib/mysql
  3. 准备并合并备份

    bash
    # 准备全量备份
    mariabackup --prepare \
      --target-dir=/backup/mariadb/full/latest \
      --apply-log-only \
      --parallel=4
    
    # 合并所有增量备份(按照时间顺序)
    for incr_dir in $(find /backup/mariadb/incremental -type d -name "202312*" | sort); do
      mariabackup --prepare \
        --target-dir=/backup/mariadb/full/latest \
        --incremental-dir=$incr_dir \
        --apply-log-only \
        --parallel=4
    done
    
    # 完成备份准备
    mariabackup --prepare \
      --target-dir=/backup/mariadb/full/latest \
      --parallel=4
  4. 执行恢复

    bash
    mariabackup --copy-back \
      --target-dir=/backup/mariadb/full/latest \
      --datadir=/var/lib/mysql \
      --parallel=4
  5. 启动主库并验证

    bash
    systemctl start mariadb
    mysql -u root -p -e "SHOW MASTER STATUS;"

场景2:恢复到特定时间点(结合 Binlog)

  1. 执行增量恢复到最近的增量备份点

    bash
    # 准备全量备份
    mariabackup --prepare \
      --target-dir=/backup/mariadb/full/20231227_120000 \
      --apply-log-only \
      --parallel=4
    
    # 合并增量备份到 20231228_060000
    mariabackup --prepare \
      --target-dir=/backup/mariadb/full/20231227_120000 \
      --incremental-dir=/backup/mariadb/incremental/20231227_180000 \
      --apply-log-only \
      --parallel=4
    
    mariabackup --prepare \
      --target-dir=/backup/mariadb/full/20231227_120000 \
      --incremental-dir=/backup/mariadb/incremental/20231228_060000 \
      --parallel=4
  2. 恢复到数据目录

    bash
    mariabackup --copy-back \
      --target-dir=/backup/mariadb/full/20231227_120000 \
      --datadir=/var/lib/mysql \
      --parallel=4
    
    chown -R mysql:mysql /var/lib/mysql
  3. 启动 MariaDB 服务

    bash
    systemctl start mariadb
  4. 应用 Binlog 到特定时间点

    bash
    # 查看备份的 Binlog 位置
    cat /backup/mariadb/full/20231227_120000/xtrabackup_binlog_info
    
    # 应用 Binlog 从备份位置到特定时间点
    mysqlbinlog --start-position=123456 \
      --stop-datetime="2023-12-28 08:30:00" \
      /var/lib/mysql/binlog.000001 \
      /var/lib/mysql/binlog.000002 \
      | mysql -u root -p

场景3:从库重建,应用增量备份

  1. 停止从库服务

    bash
    systemctl stop mariadb
  2. 清理数据目录

    bash
    rm -rf /var/lib/mysql/*
  3. 恢复全量备份

    bash
    mariabackup --copy-back \
      --target-dir=/backup/mariadb/full/latest \
      --datadir=/var/lib/mysql \
      --parallel=4
    
    chown -R mysql:mysql /var/lib/mysql
  4. 启动从库并配置复制

    bash
    systemctl start mariadb
    
    # 获取全量备份的 Binlog 位置
    BINLOG_INFO=$(cat /backup/mariadb/full/latest/xtrabackup_binlog_info)
    BINLOG_FILE=$(echo $BINLOG_INFO | awk '{print $1}')
    BINLOG_POS=$(echo $BINLOG_INFO | awk '{print $2}')
    
    # 配置从库复制
    mysql -u root -p -e "STOP SLAVE;"
    mysql -u root -p -e "CHANGE MASTER TO MASTER_HOST='master_host', MASTER_USER='repl', MASTER_PASSWORD='repl_password', MASTER_LOG_FILE='$BINLOG_FILE', MASTER_LOG_POS=$BINLOG_POS;"
    mysql -u root -p -e "START SLAVE;"
    mysql -u root -p -e "SHOW SLAVE STATUS\G;"

增量恢复性能优化

1. 备份准备阶段优化

  • 增加并行度:根据 CPU 核心数调整 --parallel 参数
  • 使用 SSD 存储:SSD 的 I/O 性能远高于 HDD,可大幅提升备份准备速度
  • 合理安排备份合并顺序:严格按照增量备份的创建顺序合并,避免重复操作

2. 恢复阶段优化

  • 使用 --move-back 代替 --copy-back:直接移动文件而不是复制,速度更快
  • 关闭二进制日志:恢复过程中临时关闭二进制日志,减少写入开销
  • 调整 innodb_buffer_pool_size:增加缓冲池大小,提高恢复速度

3. 恢复后优化

  • 运行 ANALYZE TABLE:更新表统计信息,提高查询性能
    bash
    mysql -u root -p -e "ANALYZE TABLE mydatabase.mytable;"
  • 运行 OPTIMIZE TABLE:优化表空间,减少碎片
    bash
    mysql -u root -p -e "OPTIMIZE TABLE mydatabase.mytable;"

常见问题(FAQ)

Q1: 增量恢复失败,提示 "cannot apply incremental backup to full backup"?

A: 这通常是因为增量备份与全量备份不匹配,或者合并顺序错误。

  • 确保增量备份是基于指定的全量备份创建的
  • 检查 xtrabackup_checkpoints 文件,确保 backup_type 正确
  • 按照增量备份的创建顺序依次合并

Q2: 合并增量备份时提示 "xtrabackup_logfile corrupted"?

A: 这是因为 Redo Log 文件损坏。可以尝试以下解决方案:

  • 检查增量备份文件的完整性
  • 重新创建增量备份
  • 跳过损坏的增量备份,使用上一个可用的增量备份

Q3: 恢复后数据不完整,缺少某些增量备份的数据?

A: 可能是因为:

  • 增量备份顺序合并错误
  • 遗漏了某个增量备份
  • 增量备份文件损坏

解决方案

  • 检查增量备份的合并顺序,确保按照时间顺序合并
  • 验证所有增量备份文件的完整性
  • 从备份日志中查找错误信息

Q4: 如何确定增量备份的合并顺序?

A: 可以通过以下方式确定:

  1. 查看备份目录的创建时间:
    bash
    ls -la /backup/mariadb/incremental/  # 按照时间排序
  2. 查看 xtrabackup_checkpoints 文件中的 lsn 值:
    bash
    cat /backup/mariadb/incremental/*/xtrabackup_checkpoints | grep lsn
    按照 lsn 值的升序合并

Q5: 增量恢复后,从库复制失败?

A: 这可能是因为:

  • 恢复后的 Binlog 位置不正确
  • 主库的 Binlog 文件已被清理
  • 从库的复制配置错误

解决方案

  1. xtrabackup_binlog_info 文件中获取正确的 Binlog 位置
  2. 确保主库的 Binlog 保留时间足够长
  3. 重新配置从库复制

最佳实践

  1. 严格按照时间顺序合并增量备份:增量备份必须按照创建顺序依次合并,否则会导致数据不一致
  2. 定期测试增量恢复流程:至少每季度进行一次增量恢复测试,确保备份可用
  3. 记录增量备份的依赖关系:记录每个增量备份基于哪个全量备份创建,便于恢复时查找
  4. 使用自动化脚本:编写增量恢复脚本,减少手动操作错误
  5. 监控恢复过程:恢复过程中监控系统资源使用和日志输出
  6. 验证恢复结果:恢复完成后验证数据完整性、表结构和业务功能
  7. 保持备份和恢复工具版本一致:使用与备份时相同版本的工具进行恢复
  8. 结合 Binlog 进行时间点恢复:对于关键业务,建议结合 Binlog 进行更精确的时间点恢复
  9. 定期清理过期增量备份:根据备份保留策略清理旧的增量备份,避免存储空间浪费
  10. 文档化恢复流程:将增量恢复流程纳入运维文档,便于团队成员参考

通过遵循以上步骤和最佳实践,可以确保 MariaDB 增量恢复的顺利进行,快速恢复数据库服务到指定时间点,减少业务中断时间和数据丢失。