是基于MySQL的服务器的开源热备份实用程序,在备份期间不会锁定数据库。支持的InnoDB,XtraDB和MyISAM表引擎。
# 简介
提示:可以结合rsync将备份文件复制到远程服务器上实现灾备,再使用mysqlbinlog工具同步binlog到远程服务器上以备份增量数据
Percona XtraBackup (opens new window)是基于MySQL的服务器的开源热备份实用程序,在备份期间不会锁定数据库。支持的InnoDB,XtraDB和MyISAM表引擎。
版本选择:
- xtrabackup2.4支持(推荐):MySQL 5.1,5.5,5.6和5.7
- xtrabackup8.0支持:MySQL8.0.0,MySQL8.0.20及以后的版本不支持
# 安装
yum install -y https://repo.percona.com/yum/percona-release-latest.noarch.rpm
percona-release enable-only tools release
yum install -y percona-xtrabackup-24 qpress
# 全量备份与恢复
# 创建备份所使用的用户
CREATE USER 'backupuser'@'localhost' IDENTIFIED BY 'PASSWORD';
GRANT RELOAD, LOCK TABLES, PROCESS, REPLICATION CLIENT ON *.* TO 'backupuser'@'localhost';
FLUSH PRIVILEGES;
# 全量备份
参数说明:
--backup 参数指定为备份的操作
--target-dir=xxx 目录必须不存在或者为空,否则会备份失败
--compress 压缩备份
--databases='mysql sys information_schema performance_schema test' 指定备份的数据库,MySQL自带的库一定要写上,否则恢复后无法启动
--databases-exclude="db1 db2" 指定不备份的库
--tables-exclude="db.table1 db.table2" 指定不备份的表
执行备份:
mkdir -p /data/backups/
xtrabackup --user=backupuser --password="PASSWORD" --backup --target-dir=/data/backups/
# 全量恢复
注意事项:
- 一般情况下为了不影响线上业务,会使用新的MySQL实例进行恢复,然后导出误删的数据进行恢复。
- 如果备份时压缩过,则需要先解压缩,然后再执行恢复的步骤,解压缩:
xtrabackup --decompress --target-dir=/data/backups/
恢复步骤: 1、恢复前停止MySQL服务,MySQL的datadir目录必须为空。
systemctl stop mysqld
mv /var/lib/mysql /var/lib/mysqlbackup
- 准备恢复,检查是否可恢复,检查中途不能中断 --prepare参数指定为检查恢复的操作
xtrabackup --user=backupuser --password="PASSWORD" --prepare --target-dir=/data/backups
- 执行恢复,准备恢复无误后操作
--copy-back参数指定为恢复的操作
xtrabackup --user=backupuser --password="PASSWORD" --copy-back --target-dir=/data/backups
也可以使用文件复制的方式
rsync -avrP /data/backups/ /var/lib/mysql/
- 恢复完成后修正所属者
chown -R mysql:mysql /var/lib/mysql
- 启动MySQL
systemctl start mysqld
# 增量备份与恢复
注意事项:
- 先全量备份,再增量备份,例如每周一次全量备份,基于全量备份每天做一次增量备份,或者每天一次全量备份,每小时一次增量备份。
- 增量备份可以基于全量备份,也可以基于上次增量备份,根据磁盘容量和数据量大小来选择。
- 恢复的时候先执行准备恢复,将增量数据合并到全量数据上,最后执行全量数据恢复,需要注意的是最后一次增量恢复准备时不用加参数:--apply-only-log
# 备份
mkdir -p /data/backups
#全量备份
xtrabackup --user=backupuser --password="PASSWORD" --backup --target-dir=/data/backups/base
#增量备份一
xtrabackup --user=backupuser --password="PASSWORD" --backup --target-dir=/data/backups/inc1 --incremental-basedir=/data/backups/base
#增量备份二,基于增量备份一
xtrabackup --user=backupuser --password="PASSWORD" --backup --target-dir=/data/backups/inc2 --incremental-basedir=/data/backups/inc1
# 恢复
# 恢复准备
--apply-only-log 来防止回滚阶段
systemctl stop mysqld
mv /var/lib/mysql /var/lib/mysqlbackup
#恢复准备全量备份
xtrabackup --user=backupuser --password="PASSWORD" --prepare --apply-log-only --target-dir=/data/backups/base
#恢复准备增量备份一,这时会将增量备份数据合并到全量备份中
xtrabackup --user=backupuser --password="PASSWORD" --prepare --apply-log-only --target-dir=/data/backups/base --incremental-dir=/data/backups/inc1
#恢复准备增量备份二,这时会将增量备份数据合并到全量备份中
xtrabackup --user=backupuser --password="PASSWORD" --prepare --target-dir=/data/backups/base --incremental-dir=/data/backups/inc2
# 执行恢复
xtrabackup --user=backupuser --password="PASSWORD" --copy-back --target-dir=/data/backups/base
chown -R mysql:mysql /var/lib/mysql
systemctl start mysqld
# MySQL binlog基于时间点恢复
xtrabackup备份数据后会记录MySQL的binlog日志的文件名称和position信息到xtrabackup_binlog_info文件中(需开启MySQL的binlog)
开启binlog vim /etc/my.cnf
[mysqld]
log_bin=mysql-bin
server-id=1
expire_logs_days=30
根据binlog基于时间点恢复数据 注意事项:恢复前关闭binlog日志
mysql -uroot -proot -e 'set sql_log_bin=0'
MASTER_LOG_POS=`head -n 1 /data/backups/xtrabackup_binlog_info|cut -f2`
MASTER_LOG_FILE=`head -n 1 /data/backups/xtrabackup_binlog_info|cut -f1`
mysqlbinlog --start-position=$MASTER_LOG_POS --stop-datetime="2022-07-05 14:13:00" /var/lib/mysql/$MASTER_LOG_FILE > data.sql
mysql -uroot -proot < data.sql
mysql -uroot -proot -e 'set sql_log_bin=1'
# 备份脚本
方案一:每天01:00一次全量备份,7点至23点每一小时增量备份,保留最近30天的备份
echo "0 1,7-23 * * * root /usr/local/scripts/xtrabackup.sh --user=backupuser --password=PASSWORD" >> /etc/crontab
方案二:每周一01:00一次全量备份,每天01:00增量备份,保留最近30天的备份
echo "0 1 * * * root /usr/local/scripts/xtrabackup.sh --backup-full-dirname=`date +%Y-%U` --backup-inc-dirname=`date +%u-%Y%m%d` --user=backupuser --password=PASSWORD" >> /etc/crontab
mkdir /usr/local/scripts
vim /usr/local/scripts/xtrabackup.sh
chmod a+x /usr/local/scripts/xtrabackup.sh
##!/bin/bash
BACKUP_DIR=/data/backups
BACKUP_DAYS=30
BACKUP_COMPRESS=1
BACKUP_FULL_DIRNAME=`date +%Y-%m-%d`
BACKUP_INC_DIRNAME=`date +%H-%Y%m%d`
MYSQL_USER="root"
MYSQL_PASSWORD="root"
MYSQL_PORT=3306
get_help() {
echo '用法:'
echo 'xtrabackup.sh [options]...'
echo 'options:'
echo ' --backup-dir=/data/backups 备份保存的路径'
echo ' --backup-days=30 备份保留几天'
echo ' --compress=1 是否压缩备份'
echo ' --backup-full-dirname=`date +%Y-%m-%d` 全量备份目录名称,可用于控制全量备份周期,如每天:date +%Y-%m-%d,每周:date +%Y-%U'
echo ' --backup-inc-dirname=`date +%H-%Y%m%d` 增量备份目录名称,可用于控制增量备份周期,如每天:%H-%Y%m%d,每周:date +%u-%Y%m%d'
echo ' --user=root MySQL用户'
echo ' --password=root MySQL密码'
echo ' --port=3306 MySQL端口'
}
ARGS=`getopt -o h --long help,backup-dir:,backup-days:,compress:,backup-full-dirname:,backup-inc-dirname:,user:,password:,port: -n "$0" -- "$@"`
if [ $? != 0 ]; then
echo "Terminating..."
exit 1
fi
#echo ARGS=[$ARGS]
eval set -- "${ARGS}"
while true
do
case "$1" in
-h|--help)
get_help
shift
exit 0
;;
--backup-dir)
BACKUP_DIR=$2
shift 2
;;
--backup-days)
BACKUP_DAYS=$2
shift 2
;;
--compress)
BACKUP_COMPRESS=$2
shift 2
;;
--backup-full-dirname)
BACKUP_FULL_DIRNAME=$2
shift 2
;;
--backup-inc-dirname)
BACKUP_INC_DIRNAME=$2
shift 2
;;
--user)
MYSQL_USER=$2
shift 2
;;
--password)
MYSQL_PASSWORD=$2
shift 2
;;
--port)
MYSQL_PORT=$2
shift 2
;;
--)
shift
break
;;
*)
echo "Internal error!"
exit 1
;;
esac
done
XTRABACKUP=/usr/bin/xtrabackup
BACKUP_DIR_TERM=$BACKUP_DIR/$BACKUP_FULL_DIRNAME
BACKUP_FULL_DIR=$BACKUP_DIR_TERM/full
BACKUP_INC_DIR=$BACKUP_DIR_TERM/$BACKUP_INC_DIRNAME
LOGFILE=$BACKUP_DIR/backup.log
XTRALOGFILE=$BACKUP_DIR/xtrabackup.log
backup_run() {
backup_init
backup_database
backup_clean
}
backup_init() {
if [ ! -f $XTRABACKUP ];then
echo "$XTRABACKUP 不存在"
exit 1
fi
if [ ! -d $BACKUP_DIR_TERM ];then
mkdir -p $BACKUP_DIR_TERM
fi
}
backup_clean() {
if [ "$BACKUP_DIR" != "/" ];then
find $BACKUP_DIR -type d -mtime +$BACKUP_DAYS -exec rm {} \; > /dev/null 2>&1
fi
}
save_log() {
echo $1;
echo "[`date +'%Y-%m-%d %H:%M:%S'`] $1" >> $LOGFILE
}
backup_database() {
COMMAND="$XTRABACKUP --user=$MYSQL_USER --password=$MYSQL_PASSWORD --port=$MYSQL_PORT --backup"
NEWEST_DIRNAME=`ls -t $BACKUP_DIR_TERM | head -n 1`
if [ "$NEWEST_DIRNAME" = "" ];then
COMMAND="$COMMAND --target-dir=$BACKUP_FULL_DIR"
else
BASEDIR=$BACKUP_DIR_TERM/$NEWEST_DIRNAME
COMMAND="$COMMAND --target-dir=$BACKUP_INC_DIR --incremental-basedir=$BASEDIR"
fi
if [ $BACKUP_COMPRESS -eq 1 ];then
COMMAND="$COMMAND --compress"
fi
save_log "beging backup:$COMMAND"
$($COMMAND >> $XTRALOGFILE 2>&1)
if [ $? -eq 0 ];then
save_log "backup successful"
else
save_log "backup failure"
fi
}
backup_run
🕑 最后更新时间: 2022-10-16 15:05