Skip to content

MariaDB 全量恢复

全量恢复概述

全量恢复是指从完整的备份文件中恢复数据库的过程,是最常用的恢复方式。根据备份类型的不同,全量恢复可以分为物理全量恢复和逻辑全量恢复。

恢复类型比较

恢复类型适用场景恢复速度数据一致性灵活性工具
物理全量恢复大规模数据库、快速恢复需求mariabackup
逻辑全量恢复小型数据库、单库/单表恢复mysqldump、mydumper

物理全量恢复(使用 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
# 使用 mariabackup 解压备份
mariabackup --decompress \
  --target-dir=/backup/mariadb/full/latest \
  --parallel=4

如果备份尚未准备(prepare),需要先执行准备操作:

bash
# 准备备份文件
mariabackup --prepare \
  --target-dir=/backup/mariadb/full/latest \
  --parallel=4

执行全量恢复

1. 使用 mariabackup --copy-back 恢复

bash
# 执行恢复操作
mariabackup --copy-back \
  --target-dir=/backup/mariadb/full/latest \
  --datadir=/var/lib/mysql \
  --parallel=4

2. 或使用 mariabackup --move-back 恢复(更快,但会删除备份文件)

bash
# 执行恢复操作(会删除原始备份文件)
mariabackup --move-back \
  --target-dir=/backup/mariadb/full/latest \
  --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;"

逻辑全量恢复(使用 mysqldump)

恢复准备

1. 确保 MariaDB 服务正在运行

bash
# 检查服务状态
systemctl status mariadb

# 如果未运行,启动服务
systemctl start mariadb

2. 创建目标数据库(如果不存在)

bash
# 连接数据库
mysql -u root -p

# 创建数据库
CREATE DATABASE mydatabase CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

# 退出
EXIT;

执行全量恢复

1. 恢复单个数据库

bash
# 恢复单个数据库
mysql -u root -p mydatabase < /backup/mariadb/mydatabase_full_20231227_120000.sql

# 或从压缩文件恢复
gunzip -c /backup/mariadb/mydatabase_full_20231227_120000.sql.gz | mysql -u root -p mydatabase

2. 恢复所有数据库

bash
# 恢复所有数据库
mysql -u root -p < /backup/mariadb/full_all_20231227_120000.sql

# 或从压缩文件恢复
gunzip -c /backup/mariadb/full_all_20231227_120000.sql.gz | mysql -u root -p

3. 使用 mysqlimport 恢复 CSV/TSV 数据

如果备份是 CSV 或 TSV 格式,可以使用 mysqlimport 工具恢复:

bash
# 恢复 CSV 数据
mysqlimport --local --fields-terminated-by=, --lines-terminated-by=\n -u root -p mydatabase /backup/mariadb/mytable.csv

# 恢复 TSV 数据
mysqlimport --local --fields-terminated-by=\t --lines-terminated-by=\n -u root -p mydatabase /backup/mariadb/mytable.tsv

恢复后验证

bash
# 连接数据库并验证
mysql -u root -p -e "SHOW DATABASES;"
mysql -u root -p -e "USE mydatabase; SHOW TABLES;"
mysql -u root -p -e "SELECT COUNT(*) FROM mydatabase.mytable;"
mysql -u root -p -e "SELECT * FROM mydatabase.mytable LIMIT 10;"

逻辑全量恢复(使用 mydumper/myloader)

恢复准备

1. 确保 MariaDB 服务正在运行

bash
systemctl status mariadb

2. 创建目标数据库(如果不存在)

bash
mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS mydatabase CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

执行全量恢复

bash
# 使用 myloader 恢复
myloader \
  --user=root \
  --password=password \
  --database=mydatabase \
  --directory=/backup/mariadb/mydumper_20231227_120000 \
  --threads=8 \
  --overwrite-tables \
  --verbose=3

恢复后验证

bash
# 验证恢复结果
mysql -u root -p -e "USE mydatabase; SHOW TABLES;"
mysql -u root -p -e "SELECT COUNT(*) 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 --copy-back \
      --target-dir=/backup/mariadb/full/latest \
      --datadir=/var/lib/mysql \
      --parallel=4
  4. 启动主库

    bash
    systemctl start mariadb
  5. 重新配置从库

    bash
    # 在主库上创建复制用户
    mysql -u root -p -e "GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%' IDENTIFIED BY 'repl_password';"
    
    # 获取主库的二进制日志位置
    mysql -u root -p -e "SHOW MASTER STATUS;"
    
    # 在从库上重新配置复制
    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.000001', MASTER_LOG_POS=123456;"
    mysql -u root -p -e "START SLAVE;"
    mysql -u root -p -e "SHOW SLAVE STATUS\G;"

场景2:从库重建

  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
  4. 配置从库复制

    bash
    # 启动从库
    systemctl start mariadb
    
    # 配置复制
    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.000001', MASTER_LOG_POS=123456;"
    mysql -u root -p -e "START SLAVE;"
    mysql -u root -p -e "SHOW SLAVE STATUS\G;"

场景3:测试环境恢复

  1. 创建测试数据库

    bash
    mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS test_mydatabase CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
  2. 恢复到测试数据库

    bash
    # 使用 mysqldump 恢复到不同数据库名
    mysqldump --no-create-db -u root -p mydatabase < /backup/mariadb/mydatabase_full_20231227_120000.sql | mysql -u root -p test_mydatabase
  3. 验证测试数据库

    bash
    mysql -u root -p -e "USE test_mydatabase; SELECT COUNT(*) FROM mytable;"

恢复性能优化

1. 物理恢复优化

  • 使用 --move-back 代替 --copy-back:直接移动文件而不是复制,速度更快
  • 增加并行度:根据 CPU 核心数调整 --parallel 参数
  • 使用 SSD 存储:SSD 的 I/O 性能远高于 HDD,可大幅提升恢复速度
  • 关闭二进制日志:恢复过程中临时关闭二进制日志,减少写入开销
    bash
    # 修改配置文件临时关闭二进制日志
    sed -i 's/log_bin=/#log_bin=/g' /etc/my.cnf
    # 恢复完成后重新开启

2. 逻辑恢复优化

  • 使用 myloader 代替 mysql:myloader 支持并行恢复,速度更快
  • 增加 myloader 的 --threads 参数:根据 CPU 核心数调整并行线程数
  • 关闭二进制日志和慢查询日志:恢复过程中临时关闭,减少写入开销
  • 调整 innodb_buffer_pool_size:增加缓冲池大小,提高恢复速度
  • 使用 --disable-keys:恢复 MyISAM 表时禁用索引,恢复后重建
    bash
    mysql -u root -p -e "SET FOREIGN_KEY_CHECKS=0; SET UNIQUE_CHECKS=0; SOURCE /backup/mariadb/mydatabase.sql; SET FOREIGN_KEY_CHECKS=1; SET UNIQUE_CHECKS=1;"

常见问题(FAQ)

Q1: mariabackup 恢复失败,提示 "The datadir must be empty"?

A: 这是因为数据目录不为空,需要先清理数据目录:

bash
rm -rf /var/lib/mysql/*

或者使用 --force-non-empty-directories 参数(不推荐,可能导致数据不一致):

bash
mariabackup --copy-back \
  --target-dir=/backup/mariadb/full/latest \
  --datadir=/var/lib/mysql \
  --force-non-empty-directories

Q2: 恢复后 MariaDB 无法启动,提示权限错误?

A: 确保数据目录的权限正确:

bash
chown -R mysql:mysql /var/lib/mysql
chmod -R 700 /var/lib/mysql

Q3: 恢复后数据不一致,某些表缺失或数据错误?

A: 检查备份文件是否完整和一致:

bash
# 验证备份完整性
mariabackup --prepare \
  --target-dir=/backup/mariadb/full/latest \
  --check

Q4: 逻辑恢复速度太慢,如何优化?

A: 可以尝试以下优化措施:

  • 使用 myloader 代替 mysql 进行并行恢复
  • 关闭二进制日志和慢查询日志
  • 调整 innodb_buffer_pool_size 为物理内存的 50-70%
  • 使用 --disable-keys 和 --foreign-key-checks=0 参数

Q5: 恢复后从库复制失败,提示 "Got fatal error 1236 from master when reading data from binary log"?

A: 这通常是因为主库的二进制日志文件损坏或丢失,需要重新配置复制:

  1. 在主库上获取新的二进制日志位置
    bash
    mysql -u root -p -e "SHOW MASTER STATUS;"
  2. 在从库上重新配置复制
    bash
    mysql -u root -p -e "STOP SLAVE;"
    mysql -u root -p -e "CHANGE MASTER TO MASTER_LOG_FILE='new_binlog_file', MASTER_LOG_POS=new_position;"
    mysql -u root -p -e "START SLAVE;"
    mysql -u root -p -e "SHOW SLAVE STATUS\G;"

最佳实践

  1. 定期测试恢复流程:至少每季度进行一次全量恢复测试,确保备份可用
  2. 记录恢复步骤:详细记录恢复流程,包括命令、参数和注意事项
  3. 使用自动化脚本:编写恢复脚本,减少手动操作错误
  4. 监控恢复过程:恢复过程中监控系统资源使用和日志输出
  5. 验证恢复结果:恢复完成后验证数据完整性、表结构和业务功能
  6. 恢复后性能检查:检查恢复后数据库的性能,确保正常运行
  7. 保持备份和恢复工具版本一致:使用与备份时相同版本的工具进行恢复
  8. 文档化恢复流程:将恢复流程纳入运维文档,便于团队成员参考

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