Skip to content

MySQL 全量恢复

全量恢复是数据库恢复的基础,用于将数据库恢复到备份时的完整状态。本文将详细介绍MySQL全量恢复的概念、恢复方法、步骤和生产环境最佳实践。

全量恢复概述

什么是全量恢复

全量恢复是指使用完整的备份文件将数据库恢复到备份时的状态。它是最基本也是最常用的恢复方式,适用于各种数据丢失场景,如数据库崩溃、数据误删除、硬件故障等。

全量恢复的类型

根据备份类型的不同,全量恢复可以分为:

  • 逻辑备份恢复:使用mysqldump、mydumper等工具生成的备份文件进行恢复
  • 物理备份恢复:使用xtrabackup、MySQL Enterprise Backup等工具生成的备份文件进行恢复

全量恢复的应用场景

  • 数据库崩溃恢复:当数据库因硬件故障、软件错误等原因崩溃时,使用全量恢复将数据库恢复到正常状态
  • 数据误删除恢复:当数据被误删除时,使用全量恢复将数据恢复到删除前的状态
  • 测试环境搭建:使用生产环境的全量备份搭建测试环境
  • 数据库迁移:使用全量备份进行数据库迁移

版本差异考虑

不同MySQL版本的全量恢复特性存在差异:

特性MySQL 5.6MySQL 5.7MySQL 8.0
逻辑备份恢复速度较慢较快
物理备份恢复速度较快更快
并行恢复支持不支持支持支持
加密备份恢复不支持支持(企业版)支持
克隆插件恢复不支持不支持支持

逻辑备份全量恢复

恢复前准备

环境检查

bash
# 1. 检查MySQL服务状态
mysqladmin -u root -p ping

# 2. 检查目标数据库是否存在
mysql -u root -p -e "SHOW DATABASES;"

# 3. 检查磁盘空间
df -h /var/lib/mysql

# 4. 检查备份文件完整性
md5sum -c backup.sql.md5

恢复策略选择

恢复场景建议策略
数据库完全丢失直接恢复到原数据库位置
数据误删除恢复到临时数据库,然后提取需要的数据
测试环境搭建恢复到新的数据库实例
数据库迁移恢复到目标服务器

恢复步骤

恢复到原数据库

bash
# 1. 停止MySQL服务
systemctl stop mysqld

# 2. 清空数据目录(可选,根据实际情况决定)
# rm -rf /var/lib/mysql/*

# 3. 启动MySQL服务
systemctl start mysqld

# 4. 创建数据库(如果备份文件不包含CREATE DATABASE语句)
mysql -u root -p -e "CREATE DATABASE dbname;"

# 5. 执行恢复
mysql -u root -p dbname < backup.sql

# 6. 检查恢复结果
mysql -u root -p -e "USE dbname; SHOW TABLES;"

恢复到临时数据库

bash
# 1. 创建临时数据库
mysql -u root -p -e "CREATE DATABASE temp_db;"

# 2. 执行恢复
mysql -u root -p temp_db < backup.sql

# 3. 验证数据
mysql -u root -p -e "USE temp_db; SELECT COUNT(*) FROM users;"

# 4. 提取需要的数据(示例:将users表数据恢复到原数据库)
mysql -u root -p -e "INSERT INTO dbname.users SELECT * FROM temp_db.users WHERE id > 1000;"

# 5. 删除临时数据库
mysql -u root -p -e "DROP DATABASE temp_db;"

使用mydumper备份的恢复

bash
# 使用myloader恢复mydumper生成的备份
myloader -u root -p password -d /path/to/backup -B dbname -o

恢复后验证

bash
# 1. 验证数据库和表存在性
mysql -u root -p -e "USE dbname; SHOW TABLES;"

# 2. 验证数据完整性
mysql -u root -p -e "USE dbname; SELECT COUNT(*) FROM users;"

# 3. 验证数据一致性(与备份前记录的数据量比较)
mysql -u root -p -e "USE dbname; SELECT table_name, table_rows FROM information_schema.tables WHERE table_schema='dbname';"

# 4. 验证数据库服务状态
mysqladmin -u root -p status

# 5. 验证应用程序连接
# 使用应用程序测试连接到数据库

物理备份全量恢复

恢复前准备

环境检查

bash
# 1. 检查MySQL服务状态
mysqladmin -u root -p ping

# 2. 检查数据目录
ls -la /var/lib/mysql

# 3. 检查磁盘空间
df -h /var/lib/mysql

# 4. 检查备份文件完整性
xtrabackup --prepare --target-dir=/path/to/backup

恢复步骤

使用xtrabackup备份的恢复

bash
# 1. 停止MySQL服务
systemctl stop mysqld

# 2. 备份当前数据目录(可选)
mv /var/lib/mysql /var/lib/mysql_bak
mkdir -p /var/lib/mysql

# 3. 准备备份文件
xtrabackup --prepare --target-dir=/path/to/backup

# 4. 恢复备份
xtrabackup --copy-back --target-dir=/path/to/backup --datadir=/var/lib/mysql

# 5. 设置权限
chown -R mysql:mysql /var/lib/mysql

# 6. 启动MySQL服务
systemctl start mysqld

# 7. 验证恢复结果
mysql -u root -p -e "SHOW DATABASES;"

直接替换数据目录的恢复

bash
# 1. 停止MySQL服务
systemctl stop mysqld

# 2. 清空数据目录
rm -rf /var/lib/mysql/*

# 3. 复制备份文件到数据目录
cp -r /path/to/backup/* /var/lib/mysql/

# 4. 设置权限
chown -R mysql:mysql /var/lib/mysql

# 5. 启动MySQL服务
systemctl start mysqld

# 6. 验证恢复结果
mysql -u root -p -e "SHOW DATABASES;"

恢复后验证

bash
# 1. 验证数据库服务启动
systemctl status mysqld

# 2. 验证数据库连接
mysql -u root -p -e "SELECT VERSION();"

# 3. 验证数据库和表
mysql -u root -p -e "USE dbname; SHOW TABLES;"

# 4. 验证数据完整性
mysql -u root -p -e "USE dbname; SELECT COUNT(*) FROM users;"

# 5. 验证InnoDB表空间
mysql -u root -p -e "SHOW TABLE STATUS LIKE 'users';"

自动恢复脚本

逻辑备份自动恢复脚本

bash
#!/bin/bash

# 配置信息
BACKUP_FILE="/backup/mysql/dbname_full_20231201.sql"
DB_USER="root"
DB_PASS="your_password"
DB_NAME="dbname"
LOG_FILE="/backup/mysql/recovery.log"

# 日志函数
log() {
  echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> $LOG_FILE
}

log "Starting full recovery for database: $DB_NAME"
log "Using backup file: $BACKUP_FILE"

# 1. 检查备份文件存在性
if [ ! -f "$BACKUP_FILE" ]; then
  log "ERROR: Backup file not found: $BACKUP_FILE"
  exit 1
fi

# 2. 检查MySQL服务状态
if mysqladmin -u $DB_USER -p$DB_PASS ping > /dev/null 2>&1; then
  log "PASS: MySQL service is running"
else
  log "ERROR: MySQL service is not running"
  exit 1
fi

# 3. 创建数据库(如果不存在)
if ! mysql -u $DB_USER -p$DB_PASS -e "SHOW DATABASES LIKE '$DB_NAME';" | grep -q $DB_NAME; then
  log "Creating database: $DB_NAME"
  mysql -u $DB_USER -p$DB_PASS -e "CREATE DATABASE $DB_NAME;"
  if [ $? -ne 0 ]; then
    log "ERROR: Failed to create database: $DB_NAME"
    exit 1
  fi
fi

# 4. 执行恢复
log "Starting recovery process"
mysql -u $DB_USER -p$DB_PASS $DB_NAME < $BACKUP_FILE

if [ $? -eq 0 ]; then
  log "PASS: Recovery completed successfully"
else
  log "ERROR: Recovery failed"
  exit 1
fi

# 5. 恢复后验证
log "Verifying recovery results"

# 5.1 验证表存在性
TABLE_COUNT=$(mysql -u $DB_USER -p$DB_PASS -e "USE $DB_NAME; SHOW TABLES;" | grep -v "Tables_in_" | wc -l)
if [ $TABLE_COUNT -gt 0 ]; then
  log "PASS: Found $TABLE_COUNT tables in database $DB_NAME"
else
  log "WARN: No tables found in database $DB_NAME"
fi

# 5.2 验证数据完整性
# 这里假设我们知道users表应该有数据
if mysql -u $DB_USER -p$DB_PASS -e "USE $DB_NAME; SHOW TABLES LIKE 'users';" | grep -q users; then
  USER_COUNT=$(mysql -u $DB_USER -p$DB_PASS -e "USE $DB_NAME; SELECT COUNT(*) FROM users;" | grep -v "COUNT")
  log "PASS: Found $USER_COUNT users in users table"
else
  log "WARN: users table not found or empty"
fi

log "Full recovery completed successfully for database: $DB_NAME"
exit 0

物理备份自动恢复脚本

bash
#!/bin/bash

# 配置信息
BACKUP_DIR="/backup/mysql/full/20231201"
DB_DATA_DIR="/var/lib/mysql"
MYSQL_SERVICE="mysqld"
LOG_FILE="/backup/mysql/xtrabackup_recovery.log"

# 日志函数
log() {
  echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> $LOG_FILE
}

log "Starting xtrabackup full recovery"
log "Using backup directory: $BACKUP_DIR"
log "Target data directory: $DB_DATA_DIR"

# 1. 检查备份目录存在性
if [ ! -d "$BACKUP_DIR" ]; then
  log "ERROR: Backup directory not found: $BACKUP_DIR"
  exit 1
fi

# 2. 停止MySQL服务
log "Stopping MySQL service: $MYSQL_SERVICE"
systemctl stop $MYSQL_SERVICE

if [ $? -ne 0 ]; then
  log "ERROR: Failed to stop MySQL service"
  exit 1
fi

# 3. 备份当前数据目录(可选)
BAK_DIR="${DB_DATA_DIR}_$(date +'%Y%m%d%H%M%S')"
log "Backing up current data directory to: $BAK_DIR"
mv $DB_DATA_DIR $BAK_DIR
mkdir -p $DB_DATA_DIR

if [ $? -ne 0 ]; then
  log "ERROR: Failed to backup current data directory"
  systemctl start $MYSQL_SERVICE
  exit 1
fi

# 4. 准备备份文件
log "Preparing backup files"
xtrabackup --prepare --target-dir=$BACKUP_DIR > /tmp/xtrabackup_prepare.log 2>&1

if [ $? -ne 0 ]; then
  log "ERROR: Failed to prepare backup files"
  cat /tmp/xtrabackup_prepare.log >> $LOG_FILE
  rm -f /tmp/xtrabackup_prepare.log
  # 恢复原数据目录
  rm -rf $DB_DATA_DIR
  mv $BAK_DIR $DB_DATA_DIR
  systemctl start $MYSQL_SERVICE
  exit 1
fi

# 5. 恢复备份
log "Copying backup to data directory"
xtrabackup --copy-back --target-dir=$BACKUP_DIR --datadir=$DB_DATA_DIR > /tmp/xtrabackup_copy.log 2>&1

if [ $? -ne 0 ]; then
  log "ERROR: Failed to copy backup to data directory"
  cat /tmp/xtrabackup_copy.log >> $LOG_FILE
  rm -f /tmp/xtrabackup_prepare.log /tmp/xtrabackup_copy.log
  # 恢复原数据目录
  rm -rf $DB_DATA_DIR
  mv $BAK_DIR $DB_DATA_DIR
  systemctl start $MYSQL_SERVICE
  exit 1
fi

# 6. 设置权限
log "Setting permissions on data directory"
chown -R mysql:mysql $DB_DATA_DIR

if [ $? -ne 0 ]; then
  log "ERROR: Failed to set permissions"
  # 恢复原数据目录
  rm -rf $DB_DATA_DIR
  mv $BAK_DIR $DB_DATA_DIR
  systemctl start $MYSQL_SERVICE
  exit 1
fi

# 7. 启动MySQL服务
log "Starting MySQL service: $MYSQL_SERVICE"
systemctl start $MYSQL_SERVICE

if [ $? -ne 0 ]; then
  log "ERROR: Failed to start MySQL service"
  # 恢复原数据目录
  rm -rf $DB_DATA_DIR
  mv $BAK_DIR $DB_DATA_DIR
  systemctl start $MYSQL_SERVICE
  exit 1
fi

# 8. 验证MySQL服务状态
log "Verifying MySQL service status"
sleep 10

if systemctl is-active $MYSQL_SERVICE > /dev/null 2>&1; then
  log "PASS: MySQL service is running"
else
  log "ERROR: MySQL service failed to start"
  # 恢复原数据目录
  systemctl stop $MYSQL_SERVICE 2>/dev/null
  rm -rf $DB_DATA_DIR
  mv $BAK_DIR $DB_DATA_DIR
  systemctl start $MYSQL_SERVICE
  exit 1
fi

# 9. 验证数据库存在性
DB_COUNT=$(mysql -u root -S /var/lib/mysql/mysql.sock -e "SHOW DATABASES;" | grep -v "Database" | wc -l)
if [ $DB_COUNT -gt 0 ]; then
  log "PASS: Found $DB_COUNT databases"
else
  log "WARN: No databases found"
fi

# 10. 清理临时文件
rm -f /tmp/xtrabackup_prepare.log /tmp/xtrabackup_copy.log

log "Xtrabackup full recovery completed successfully"
exit 0

生产环境最佳实践

恢复前准备

  • 制定恢复计划:在恢复前制定详细的恢复计划,包括恢复步骤、时间窗口、验证方法等
  • 备份当前数据:在恢复前备份当前数据,防止恢复过程中出现问题导致数据进一步丢失
  • 通知相关人员:恢复前通知相关业务人员和运维人员,确保恢复过程得到支持
  • 准备回滚方案:制定恢复失败时的回滚方案,确保能够快速恢复到恢复前的状态

恢复过程中的注意事项

  • 选择合适的时间窗口:选择业务低峰期进行恢复,减少对业务的影响
  • 监控恢复过程:实时监控恢复过程,及时发现并解决问题
  • 记录恢复过程:详细记录恢复过程中的每一步操作和结果,便于后续分析
  • 避免中断恢复过程:恢复过程中避免中断,否则可能导致数据损坏

恢复后验证

  • 验证数据完整性:检查恢复后的数据完整性,确保所有数据都已恢复
  • 验证数据一致性:检查恢复后的数据一致性,确保数据之间的关系正确
  • 验证应用程序功能:测试应用程序的核心功能,确保恢复后应用程序能够正常运行
  • 监控数据库性能:恢复后监控数据库性能,确保恢复不会导致性能问题

不同规模数据库的恢复策略

小型数据库(< 10GB)

  • 直接使用逻辑备份恢复
  • 恢复时间短,对业务影响小
  • 可以在白天进行恢复

中型数据库(10GB - 100GB)

  • 优先使用物理备份恢复
  • 选择业务低峰期进行恢复
  • 恢复前通知相关人员

大型数据库(> 100GB)

  • 必须使用物理备份恢复
  • 选择夜间或周末进行恢复
  • 提前进行恢复演练
  • 制定详细的恢复计划和回滚方案

云环境全量恢复最佳实践

  • 利用云服务:使用云服务商提供的备份恢复功能,如AWS RDS的自动备份恢复
  • 选择合适的恢复点:根据RPO要求选择合适的恢复点
  • 验证恢复结果:恢复后验证数据完整性和应用程序功能
  • 监控恢复性能:监控云数据库的恢复性能,优化恢复策略

结论

全量恢复是数据库恢复的基础,掌握全量恢复的方法和最佳实践对于保障数据库的安全性和可靠性至关重要。通过选择合适的恢复方法、制定详细的恢复计划、严格执行恢复步骤和进行充分的恢复后验证,可以确保全量恢复的成功,最大限度地减少数据丢失和业务中断。

在实际生产环境中,应该根据数据库规模、业务需求和技术条件选择合适的全量恢复策略,并定期进行恢复演练,提高应对数据丢失场景的能力。