概要
数据库备份是确保数据安全性和可用性的关键步骤之一。Percona XtraBackup是一个开源工具,用于高性能MySQL数据库备份和恢复。在本文中,我们将探讨如何使用XtraBackup来备份和恢复MySQL数据库。
备份策略:
- 本地备份:每天一次全量备份,五分钟一次增量备份
- 异地备份:在全量备份和增量备份完成后,将备份数据同步到另一台主机上面
安装XtraBackup
首先,您需要安装XtraBackup。您可以从Percona的官方网站下载适用于您的操作系统的XtraBackup软件包,并按照安装说明进行安装。
创建Mysql备份用户
CREATE USER 'xbackup'@'%' IDENTIFIED BY 'password';
GRANT RELOAD, PROCESS, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'xbackup'@'%';
flush privileges;
目录结构说明:
/app/backup/mysql/
.
├── bin
│ ├── backup_all.sh # 将数据库备份成sql的脚本,在数据恢复时调用
│ ├── backup_env.sh # 环境变量脚本
│ ├── xtrabackup_full.sh # 全量备份脚本
│ ├── xtrabackup_incremental.sh # 增量备份脚本
│ └── xtrabackup_restore.sh # 数据还原脚本
└── data # 备份文件生成目录
├── 2023-09-15_00-00-01 # 备份文件目录
│ ├── full # 全量备份文件目录
│ ├── full_backup_success_flag # 全量备份成功标志,异地备份成功后,写入远程全量备份保存目录,供增量备份时从此文件中获取远程全量备份保存目录
│ ├── full.log # 全量备份日志
│ ├── incremental # 增量备份文件目录
│ └── incremental.log # 增量备份日志
├── 2023-09-15_00-00-01_restore_temp # 数据还原时生成的临时文件
├── all_backup-20230915-091642.sql # 数据还原时backup_all.sh输出的备份文件
└── db_data # 原数据库数据文件备份目录(数据还原时生成)
环境变量脚本:backup_env.sh
在备份和还原脚本中,这些配置变量会被引用,确保脚本中的路径和MySQL连接信息替换为您的实际值
#!/bin/bash
# 说明:这是配置文件,用于存储MySQL连接信息和备份相关的路径。
# 在备份和还原脚本中,这些配置变量会被引用。
# MySQL连接信息
mysql_host="127.0.0.1"
mysql_port="3306"
mysql_user="xbackup"
mysql_password="passwork"
mysql_datadir="/home/mysql/mysql/data"
# 本地备份目录
backup_dir="/app/backup/mysql/data"
# 远程备份连接信息
remote_backup_link="root@backup.file.server"
# 远程备份目录
remote_backup_dir="/mnt/backup/mysql/data"
# XtraBackup路径
xtrabackup_path="/usr/local/xtrabackup/bin"
# 注意:请将上述MySQL连接信息替换为您的实际信息,并设置合适的备份目录。
全量备份脚本:xtrabackup_full.sh
该脚本会创建全量备份,并同步备份数据到远程服务器,定期清理过期备份。
#!/bin/bash
#set -e
#set -x
# 说明:这是一个用于执行全量备份的脚本,使用Percona XtraBackup工具。
# 该脚本会创建全量备份并定期清理过期备份。
# 获取当前脚本所在路径
cur_path=$(cd `dirname $0`; pwd)
# 导入配置文件中的公共变量
source ${cur_path}/backup_env.sh
# 备份文件保存几天
day=30
# 定义全量备份目录
date_str="$(date '+%Y-%m-%d_%H-%M-%S')"
date_backup_dir="${backup_dir}/${date_str}"
full_backup_dir="${date_backup_dir}/full"
full_log_file="${date_backup_dir}/full.log"
incremental_backup_dir="${date_backup_dir}/incremental"
# 创建全量备份目录
if [ ! -d "$full_backup_dir" ]; then
mkdir -p "${full_backup_dir}"
fi
# 使用Percona XtraBackup执行全量备份
${xtrabackup_path}/innobackupex ${full_backup_dir} --no-timestamp --host=$mysql_host --port=$mysql_port --user="${mysql_user}" --password="${mysql_password}" >"${full_log_file}" 2>&1
# 检查全量备份是否成功
if [ $? -eq 0 ]; then
echo "全量备份成功" >>"${full_log_file}"
# 全量备份成功,创建成功标志
touch ${date_backup_dir}/full_backup_success_flag
# 创建增量备份目录
if [ ! -d "$incremental_backup_dir" ]; then
mkdir -p "${incremental_backup_dir}"
fi
# 同步数据到备份盘
echo "同步全量备份数据:${date_backup_dir}" >>"${full_log_file}"
(time scp -r ${date_backup_dir} ${remote_backup_link}:${remote_backup_dir}) >>"${full_log_file}" 2>&1
if [ $? -eq 0 ]; then
echo "同步全量备份数据:${date_backup_dir},成功" >>"${full_log_file}"
echo "${remote_backup_dir}/${date_str}" >>${date_backup_dir}/full_backup_success_flag
else
echo "同步全量备份数据:${date_backup_dir},失败" >>"${full_log_file}"
fi
else
# 全量备份失败,可以在此处添加错误处理逻辑
# 重名失败的备份文件夹
mv "$date_backup_dir" "${date_backup_dir}_error"
echo "全量备份失败" >>"${full_log_file}"
exit 1
fi
# 删除超过30天的备份
prepare_delete_file=$(find "${backup_dir}" -type d -mtime +$day)
if [ -z "${prepare_delete_file}" ]; then
echo "暂无$day天前的备份文件" >>"${full_log_file}"
else
find "${backup_dir}" -type d -mtime +$day -exec rm -rf {} \;
echo "$day天前的备份文件清理完成:" >>"${full_log_file}"
echo "${prepare_delete_file}" >>"${full_log_file}"
fi
#set +x
增量备份脚本:xtrabackup_incremental.sh
该脚本会基于最新的全量备份创建增量备份,并同步备份数据到远程服务器
#!/bin/bash
#set -e
#set -x
# 说明:这是一个用于执行增量备份的脚本,使用Percona XtraBackup工具。
# 该脚本会基于最新的全量备份创建增量备份,并同步备份数据到远程服务器。
# 获取当前脚本所在路径
cur_path=$(cd `dirname $0`; pwd)
# 导入配置文件中的公共变量
source ${cur_path}/backup_env.sh
# 获取全量备份的最新目录
latest_backup=$(find "${backup_dir}" -type f -name "full_backup_success_flag" -exec dirname {} \; | grep -v '_restore_temp$' | xargs ls -td | head -n 1)
latest_full_backup="${latest_backup}/full"
incremental_log_file="${latest_backup}/incremental.log"
# 检查全量备份是否存在
if [ -f "${latest_backup}/full_backup_success_flag" ]; then
# 定义增量备份目录
date_str="$(date '+%Y-%m-%d_%H-%M-%S')"
incremental_backup_dir="${latest_backup}/incremental/${date_str}"
# 创建增量备份目录
if [ ! -d "$incremental_backup_dir" ]; then
mkdir -p "${incremental_backup_dir}"
fi
echo "开始增量备份:${incremental_backup_dir}" >>"${incremental_log_file}"
# 使用Percona XtraBackup执行增量备份,将增量备份保存到相应的目录
${xtrabackup_path}/innobackupex --incremental --no-timestamp --incremental-basedir="${latest_full_backup}" ${incremental_backup_dir} --host=$mysql_host --port=$mysql_port --user="${mysql_user}" --password="${mysql_password}" >>"${incremental_log_file}" 2>&1
# 获取远程备份目录
cur_remote_backup_dir=$(cat "${latest_backup}/full_backup_success_flag")
# 检查全量备份是否成功
if [ $? -eq 0 ]; then
echo "增量备份成功" >>"${incremental_log_file}"
cur_remote_incremental_backup_dir="${cur_remote_backup_dir}/incremental/${date_str}"
# 同步数据到备份盘
echo "同步增量数据:${incremental_backup_dir}" >>"${incremental_log_file}"
(time scp -r ${incremental_backup_dir} ${remote_backup_link}:${cur_remote_incremental_backup_dir}) >>"${incremental_log_file}" 2>&1
if [ $? -eq 0 ]; then
echo "同步增量数据:${incremental_backup_dir},成功" >>"${incremental_log_file}"
else
echo "同步增量数据:${incremental_backup_dir},失败" >>"${incremental_log_file}"
fi
else
# 全量备份失败,可以在此处添加错误处理逻辑
echo "增量备份失败" >>"${incremental_log_file}"
fi
# 同步增量日志
echo "同步增量日志:${incremental_log_file}" >>"${incremental_log_file}"
(time scp "${incremental_log_file}" "${remote_backup_link}":"${cur_remote_backup_dir}/incremental.log") >>"${incremental_log_file}" 2>&1
echo -e "\n\n\n\n" >>"${incremental_log_file}"
else
# 如果没有最新的全量备份,记录错误或采取适当的操作
echo "未找到最新有效的全量备份" >>"${incremental_log_file}"
fi
#set +x
数据还原脚本:xtrabackup_restore.sh
用户可以选择还原特定日期的备份,并选择是否还原增量备份数据
#!/bin/bash
#set -e
#set -x
# 说明:这是一个用于执行MySQL数据库数据还原的脚本,可以还原全量备份和增量备份数据。
# 用户可以选择还原特定日期的备份,并选择是否还原增量备份数据。
# 获取当前脚本所在路径
cur_path=$(cd `dirname $0`; pwd)
# 导入配置文件中的公共变量
source ${cur_path}/backup_env.sh
echo "################################################## Mysql数据还原 ##################################################"
# 列出可供还原的备份数据
available_backups=$(find "${backup_dir}" -maxdepth 1 -type d -name '[0-9]*' -exec basename {} \; | sort -r)
if [ -z "${available_backups}" ]; then
echo "暂无备份数据"
exit 1
fi
echo "请选择全量备份数据:"
for item in "${available_backups}"
do
trimmed_item=$(echo "$item" | sed 's/^ *//;s/ *$//')
echo -e "\e[32m$trimmed_item\e[0m"
done
# 提示用户输入指定备份数据
read -p "请输入要还原的全量备份日期(格式:YYYY-MM-DD_HH-MM-SS): " selected_backup_date
selected_backup_dir=${backup_dir}/${selected_backup_date}
# 检查指定的备份是否存在
if [ ! -d "${selected_backup_dir}" ]; then
echo "选择的备份不存在"
exit 1
fi
# 复制备份文件,后续还原基于复制的备份文件这样不会破坏原始备份文件
copy_selected_backup_dir="${selected_backup_dir}_restore_temp"
if [ -d "${copy_selected_backup_dir}" ]; then
rm -rf ${copy_selected_backup_dir}
fi
cp -r ${selected_backup_dir} ${copy_selected_backup_dir}
selected_full_backup_dir=${copy_selected_backup_dir}/full
selected_incremental_backup_base_dir=${copy_selected_backup_dir}/incremental
# 提示用户是否需要还原增量备份数据
read -p "是否需要还原增量备份数据?(Y/N): " restore_incremental
if [ "${restore_incremental}" == "Y" ]; then
# 列出可供还原的增量备份数据
available_incremental_backups=$(find "${selected_incremental_backup_base_dir}" -maxdepth 1 -type d -name '[0-9]*' -exec basename {} \; | sort -r)
if [ -z "${available_incremental_backups}" ]; then
echo "暂无备份数据"
exit 1
fi
echo "请选择增量备份数据:"
for item in "${available_incremental_backups}"
do
trimmed_item=$(echo "$item" | sed 's/^ *//;s/ *$//')
echo -e "\e[32m$trimmed_item\e[0m"
done
# 需要还原增量数据
read -p "请输入增量备份日期(格式:YYYY-MM-DD_HH-MM-SS): " incremental_backup_date
selected_incremental_backup_dir=${selected_incremental_backup_base_dir}/${incremental_backup_date}
# 检查指定的增量备份是否存在
if [ ! -d "${selected_incremental_backup_dir}" ]; then
echo "指定日期的增量备份不存在"
exit 1
fi
# 使用 innobackupex 还原全量和增量备份数据
innobackupex --apply-log --redo-only "${selected_full_backup_dir}"
innobackupex --apply-log --redo-only --incremental-dir="${selected_incremental_backup_dir}" "${selected_full_backup_dir}"
elif [ "${restore_incremental}" == "N" ]; then
# 不需要还原增量数据,只还原全量备份数据
innobackupex --apply-log --redo-only "${selected_full_backup_dir}"
else
echo "输入出错误!"
exit 1
fi
# 备份原数据库数据sql脚本
bash ${cur_path}/backup_all.sh
# 停止Mysql服务器
systemctl stop mysqld.service
# 创建数据库数据文件的备份目录
db_data_backup_dir=${backup_dir}/db_data/$(date '+%Y-%m-%d_%H-%M-%S')
if [ ! -d "$db_data_backup_dir" ]; then
mkdir -p "${db_data_backup_dir}"
fi
# 备份数据库数据文件
mv ${mysql_datadir} ${db_data_backup_dir}
# 恢复数据
innobackupex --copy-back ${selected_full_backup_dir}
# 授权恢复的数据文件
chown -R mysql:mysql ${mysql_datadir}
# 最后,您可以根据需要启动MySQL服务
systemctl start mysqld.service
echo "数据恢复成功!"
# 清空临时文件
if [ -d "${copy_selected_backup_dir}" ]; then
rm -rf ${copy_selected_backup_dir}
fi
#set +x
备份和还原涉及到重要的数据库操作,请谨慎测试并确保在生产环境之前使用。
配置定时任务
crontab -e
# 每天执行全量备份任务,假设在凌晨执行
0 0 * * * /app/backup/mysql/bin/backup_full.sh
# 每五分钟执行增量备份任务
*/5 * * * * /app/backup/mysql/bin/backup_incremental.sh