Mysql/MariaDB物理备份及MinIO存储—全栈教程
前言与调研
数据备份的要求:
1.备份时不能影响业务正常运行,则需要热备
2.备份效率要高(数据量不大却要备份四五个小时,这种方式肯定不能要)
3.备份的完整性(我们备份的数据不是仍在存储里就可以了,它要在出现意外故障的时候能用得上)
4.备份的最小化(存储也是要花钱的,我们当然需要,备份保留的时间最长,占用的空间越小越好)
数据库的备份分类:
l 热备份:读写不受影响(mysqldump-->innodb)
l 温备份:仅可以执行读操作(mysqldump-->myisam)
l 冷备份:离线备份,读写都不可用
l 逻辑备份:将数据导出文本文件中(mysqldump)
l 物理备份:将数据文件拷贝(xtrabackup、mysqlhotcopy)
l 完整备份:备份所有数据
l 增量备份:仅备份上次完整备份或增量备份以来变化的数据
l 差异备份:仅备份上次完整备份以来变化的数据
xtrabackup 特点
xtrabackup是一种物理备份工具,通过协议连接到mysql服务端,然后读取并复制innodb底层的"数据块",完成所谓的"物理备份"。
1、备份过程快速、可靠;
2、备份过程不会打断正在执行的事务;
3、能够基于压缩等功能节约磁盘空间和流量;
4、自动实现备份检验;
5、还原速度快;
* 热备 * 增量 * 差量
Xtrabackup有两个主要的工具:
l xtrabackup
l innobackupex
1.xtrabackup 是用来备份 InnoDB 表的,不能备份非 InnoDB 表,和 mysqld server 没有交互;
2.innobackupex 脚本用来备份非 InnoDB 表,同时会调用 xtrabackup 命令来备份 InnoDB 表,还会和 mysqld server 发送命令进行交互,如加读锁(FTWRL)、获取位点(SHOW SLAVE STATUS)等
简单来说,innobackupex 在 xtrabackup 之上做了一层封装。
一般情况下,我们是希望能备份 MyISAM 表的,虽然我们可能自己不用 MyISAM 表,但是 mysql 库下的系统表是 MyISAM 的,因此备份基本都通过 innobackupex 命令进行。
Facebook是PerconaXtraBackup中增量备份的早期采用者
注意事项记录
安装前注意事项:
使 Percona XtraBackup 版本与 Percona Server for MySQL 保持一致
运行 mariadb-backup --backup。您必须使用与您计划升级的服务器版本兼容的 mariadb-backup 版本。
例如,从 MariaDB 10.4 升级到 10.5 时,必须使用 10.4 版本的 mariadb-backup,另一个示例:从 MariaDB 10.6 升级到 10.11 时,必须使用 10.6 版本的 mariadb-backup。
目前 Xtrabackup 活跃的大版本有三个:
Xtrabackup 2.4 适用于 MySQL 5.6 和 MySQL 5.7。
Xtrabackup 8.0 适用于 MySQL 8.0。
Xtrabackup 8.1 适用于 MySQL 8.1。
上列是针对Mysql数据库的备份方式XtraBackup 针对Mariadb10.3之上的版本不兼容使用,所以要使用其自研的Mariadb Backup
Mariadb-backup 是 Percona XtraBackup 的一个分支,增加了对 MariaDB 10.1 压缩和静态数据加密的支持。它包含在 MariaDB 10.1.23 及更高版本中。
考虑到大量数据库部署需求,我这里将实验步骤分为:
1、单端控制(使用ansible批量部署软件,运行本地备份以及远端备份的脚本,配置定时任务,xtrabackup innobackupex)
2、使用脚本批量控制数据库运行(如若不然,就需要一台台配置并且每台都做定时任务,后续维护不易寻找目标)
3、配置备份存储服务器(XtraBackup本身就自带远端备份的功能规划好空间和目录就可以)
数据走向:
数据库——backup——>本地(全量增量)——>Minio(全量)
总结:
Mysql使用XtraBackup备份(区分版本),Mariadb使用Mariadb备份。
现版本汇总:
100台服务器通过 ansible 控制多个组 以版本为分组其中:
Mariadb备份命令恢复命令相同 并且Mariadb-backup无需单独下载软件包,使用yum就可以下载到yum源配套版本
Mysql 需要区分两个版本其中5.7,8.0各为一组 并且执行的备份命令也不相同,软件包也不相同
先测试一下备份和恢复吧~emmm 需要测试mariadb备份以及两种Xtarbackup版本的备份 搞三个虚拟机-.-
针对本地磁盘空间不足矣备份的情况:
使用backup自带的流式传输功能 (注意效率会降低)
要注意流式传输的解档方式较为特殊,与备份工具配套的插件有关,确认好mairadb支持和的xtrabackup支持的命令和格式可能会不相同
五、六 有相关操作
一、准备数据库环境
1.安装mariadb 10.5.x 版本,模拟生产环境的数据库版本
配置mariadb仓库
cat <<EOF > /etc/yum.repos.d/mariadb.repo
[mariadb]
name = MariaDB
baseurl = https://mirrors.aliyun.com/mariadb/yum/10.5/centos7-amd64/
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
enabled=1
gpgcheck=1
EOF
更新缓存
yum clean all
yum makecache
yum repolist
查看可用版本
#这个可以看版本号
yum search mariadb --showduplicates
安装10.5.x版本的数据库
#安装
yum -y install MariaDB-server MariaDB-client
#启动
systemctl enable mariadb --now
#设置密码
mysql_secure_installation
#开机自启
systemctl enable mariadb
#启动服务器
systemctl start mariadb
#查看版本
mysql --version
#mysql Ver 15.1 Distrib 10.5.26-MariaDB, for Linux (x86_64) using readline 5.1
2.安装MySQL 5.7版本
MySQL : 下载 MySQL Community Server (存档版本)
#拉取软件包
wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.42-linux-glibc2.12-x86_64.tar.gz
#创建用户和组
groupadd mysql && useradd -r -g mysql mysql
#解压软件包
tar -zxvf mysql-5.7.42-linux-glibc2.12-x86_64.tar.gz -C /usr/local/
mv /usr/local/mysql-5.7.42-linux-glibc2.12-x86_64 /usr/local/mysql
#创建目录赋予权限 (赋予所有mysql涉及到的目录)
mkdir -p /data/mysql
chown mysql:mysql -R /data/mysql
chown mysql:mysql -R /usr/local/mysql
chown mysql:mysql -R /tmp
修改配置文件
vim /etc/my.cnf
[mysqld]
bind-address=0.0.0.0
port=3306 #端口号
user=mysql
basedir=/usr/local/mysql #指定mysql服务目录
datadir=/data/mysql #指定数据目录
socket=/tmp/mysql.sock #指定sock文件
log-error=/data/mysql/mysql.err #指定mysql报错log存放目录
pid-file=/data/mysql/mysql.pid #指定mysql二进制文件存放目录
#character config
character_set_server=utf8mb4 #开启utf8字符集
symbolic-links=0
explicit_defaults_for_timestamp=true
初始化
cd /usr/local/mysql/bin/
nohup ./mysqld --defaults-file=/etc/my.cnf --basedir=/usr/local/mysql/ --datadir=/data/mysql/ --user=mysql --initialize &
添加变量
vim /etcprofile
export MYSQL_HOME=/usr/local/mysql/
export MYSQL_PATH=${MYSQL_HOME}/bin:${MYSQL_HOME}/lib
export PATH=$PATH:/usr/local/mysql/bin
source /etc/profile
注册mysql 为服务、添加变量
cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysql.service
systemctl enable mysql
systemctl start mysql
#Gmq224531
3.安装MySQL 8.0版本
#备份镜像源 拉取阿里云的镜像源
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
#更新缓存
yum clean all
yum makecache
#下载 mysql 源安装包
wget http://dev.mysql.com/get/mysql80-community-release-el7-8.noarch.rpm
yum localinstall -y mysql80-community-release-el7-8.noarch.rpm
#安装mysql
yum -y install mysql
密钥过旧问题解决
yum -y install mysql-community-server --nogpgcheck
vim /etc/my.cnf
[mysqld]
bind-address=0.0.0.0
port=3306 #端口号
user=mysql
basedir=/usr/local/mysql #指定mysql服务目录
datadir=/data/mysql #指定数据目录
socket=/tmp/mysql.sock #指定sock文件
log-error=/data/mysql/mysql.err #指定mysql报错log存放目录
pid-file=/data/mysql/mysql.pid #指定mysql二进制文件存放目录
#character config
character_set_server=utf8mb4 #开启utf8字符集
symbolic-links=0
explicit_defaults_for_timestamp=true
配置mysql密码
#不同的是 mysql8.0默认是有密码的需要查看一下 root用户的密码
cat /var/log/mysqld.log | grep password
#密码:UDcA-k>tt2.N
#更改密码(必须执行)
mysql_secure_installation
#123@.cOM
4.安装minio
创建服务目录
mkdir -p /service/minio
chmod 777 /service
chmod 777 /service/minio
cd /service/miniod
wget https://dl.min.io/server/minio/release/linux-amd64/minio
mkdir -p {bin,data}
touch minio.log
vim start.sh
#/bin/bash
export MINIO_ROOT_USER=admin
export MINIO_ROOT_PASSWORD=Gengmingqi.123456
nohup /service/minio/minio server --address "0.0.0.0:9000" --console-address ":9200" /service/minio/data > /service/minio/minio.log 2>&1 &
vim stop.sh
#!/bin/bash
echo "Stopping minio"
pid=`ps -ef | grep 'minio server' | grep -v grep | awk '{print $2}'`
if [ -n "$pid" ]
then
kill -9 $pid
fi
echo "Stop Success!"
给予权限
chmod 777 *
启动、停止 Minio 服务
./start
./stop
访问
http://ip:9200
二、安装备份软件
1.安装MariaDB-backup
yum install MariaDB-backup
2.安装XtraBackup 2.4
wget https://www.gmqgmq.cn/upload/percona-xtrabackup-24-2.4.29-1.el7.x86_64.rpm
#安装依赖
yum install -y perl-DBD-MySQL
wget https://www.gmqgmq.cn/upload/libev-4.15-3.el7.x86_64.rpm
rpm -ivh libev-4.15-3.el7.x86_64.rpm
yum localinstall -y percona-xtrabackup-24-2.4.29-1.el7.x86_64.rpm
3.安装Xtrabackup 8.0
解决依赖问题 有外网用yum 没有用rpm 下面两个2选1
(1)yum安装
yum -y install https://repo.percona.com/yum/percona-release-latest.noarch.rpm
yum -y install libev-4.15-7.el7.x86_64
sudo yum install epel-release -y
sudo yum install
-y
(2)rpm安装
wget ftp://ftp.icm.edu.pl/vol/rzm7/linux-centos-vault/7.4.1708/extras/x86_64/Packages/libev-4.15-7.el7.x86_64.rpm
rpm -ivh libev-4.15-7.el7.x86_64.rpm
sudo yum install epel-release -y
sudo yum install zstd -y
安装xtrabackup
yum localinstall -y percona-xtrabackup-80-8.0.35-31.1.el7.x86_64.rpm
三、备份与恢复
统一目录结构:全量、增量备份目录架构
1、Mariadb(10.5~.6)的备份与恢复
(1)全量备份 && 恢复
mariadb-backup --backup --target-dir=/backup --user=root --password=root密码
全量恢复
#在从备份还原之前,您首先需要准备备份以使数据文件一致
mariadb-backup --prepare --target-dir=/备份目录
#还原备份(数据目录必须保持为空)
rm -rf /数据目录
mariadb-backup --copy-back --target-dir=/备份目录
#重新给予数据目录权限
chown -R mysql:mysql /数据目录
#重新启动服务
systemctl restart mariadb
(2)增量备份 && 恢复
在完整备份的基础之上执行增量的备份(将后续增加的数据进行备份,而不是从头到位备份一遍)
mariabackup --backup --target-dir=/backup/inc1 --incremental-basedir=/backup --user=root --password=123.com
增量恢复
#首先,准备基本备份 也就是统一完整备份的时间
mariabackup --prepare --target-dir=/全量备份目录
#然后,将增量更改应用于基本完整备份
mariabackup --prepare --target-dir=/全量备份目录 --incremental-dir=/增量备份目录
#还原备份(数据目录必须保持为空)
rm -rf /数据目录
#恢复
mariabackup --copy-back --target-dir=/全量备份目录
#重新给予数据目录权限
chown -R mysql:mysql /var/lib/mysql/
(3)自动化备份 && 定时任务
自动备份脚本-1(每日全量备份)
注意服务器时区同步
#!/bin/bash
# 配置环境变量让 cron 的定时任务可以生效
source /etc/profile
source ~/.bashrc
export PATH=$PATH:/usr/local/sbin
# 获取本地 IP 地址
LOCAL_IP=$(hostname -I | awk '{print $1}')
# 定义备份目录和用户信息
BACKUP_BASE=/backup
FULL_BACKUP_DIR=$BACKUP_BASE/full
USER=root
PASSWORD=123.com # 注意:建议使用环境变量或配置文件存储密码
# 获取今天的日期
TODAY=$(date +"%Y%m%d") # 用于目录名和文件名,例如 "2025年04月09日备份"
TODAY_YMD=$(date +"%Y%m%d") # 用于比较日期,例如 "20250409"
# 执行全量备份
FULL_DIR=$FULL_BACKUP_DIR/$TODAY
mkdir -p "$FULL_DIR"
mariabackup --backup --target-dir="$FULL_DIR" --user="$USER" --password="$PASSWORD"
# 打包备份目录为 tar.gz 文件
TAR_FILE="$FULL_BACKUP_DIR/${TODAY}.tar.gz"
tar -zcf "$TAR_FILE" -C "$FULL_BACKUP_DIR" "$TODAY"
# 配置 MinIO 别名
mc alias set db http://192.168.100.14:9000 dvdDrcD6VeT25hGhvkaN R7gKVpMDxLy8xrikdWHsHCaaLBAZuiAnAMN8Q2Ke
# 上传 tar.gz 文件到 MinIO,并使用 IP 地址区分路径
# 上传成功后删除本地 tar.gz 文件
if mc cp "$TAR_FILE" db/mariadb-backup/dev/"$LOCAL_IP/${TODAY}.tar.gz"; then
rm -f "$TAR_FILE"
echo "上传成功,已删除本地文件: $TAR_FILE"
else
echo "上传失败,未删除本地文件: $TAR_FILE"
fi
# 删除当天的备份目录
rm -rf "$FULL_DIR"
# 删除1天前的旧文件(如果有)
SEVEN_DAYS_AGO=$(date -d "1 days ago" +%Y%m%d)
echo "删除旧备份 older than ${SEVEN_DAYS_AGO}"
for file in "${FULL_BACKUP_DIR}"/*; do
# 提取文件名中的日期部分(假设文件名格式为 "YYYY年MM月DD日备份.tar.gz")
basename=$(basename "$file")
# 将文件名转换为 YYYYMMDD 格式以便比较
if [[ $basename =~ ([0-9]{4})年([0-9]{2})月([0-9]{2})日备份\.tar\.gz ]]; then
file_date="${BASH_REMATCH[1]}${BASH_REMATCH[2]}${BASH_REMATCH[3]}"
if [[ "$file_date" < "$SEVEN_DAYS_AGO" ]]; then
echo "正在删除旧文件: $file"
rm -f "$file"
fi
fi
done
echo "备份完成,tar 文件已上传至 MinIO: db/mariadb-backup/dev/$LOCAL_IP/$LOCAL_IP/${TODAY}.tar.gz"
自动备份脚本-2(全量增量备份)
每三天一次全量备份每天一次增量备份
创建备份全量备份的目录和增量备份的目录 只保留近7天备份)
mkdir -p /backup/full
mkdir -p /backup/inc
#!/bin/bash
#配置环境变量让cron的定时任务可以生效
source /etc/profile
source ~/.bashrc
export PATH=$PATH:/usr/local/bin
# 定义备份目录和用户信息
BACKUP_BASE=/backup
FULL_BACKUP_DIR=$BACKUP_BASE/full
INC_BACKUP_DIR=$BACKUP_BASE/inc
LAST_FULL_BACKUP_FILE=$BACKUP_BASE/last_full_backup.txt
USER=root
PASSWORD=123.com # 注意:请使用安全的方式存储密码,例如通过环境变量或配置文件
#将脚本日志输出到shlog中
exec > /$BACKUP_BASE/shlog.txt 2>&1
# 获取今天的日期(YYYYMMDD格式)
TODAY=$(date +%Y%m%d)
# 如果上次全量备份记录文件不存在,则执行全量备份
if [ ! -f "$LAST_FULL_BACKUP_FILE" ]; then
# 执行全量备份
FULL_DIR=$FULL_BACKUP_DIR/$TODAY
mkdir -p $FULL_DIR
mariabackup --backup --target-dir=$FULL_DIR --user=$USER --password=$PASSWORD
if [ $? -eq 0 ]; then
echo $FULL_DIR > $LAST_FULL_BACKUP_FILE
else
echo "全量备份失败"
exit 1
fi
else
# 读取上次全量备份的目录
LAST_FULL_DIR=$(cat $LAST_FULL_BACKUP_FILE)
LAST_DATE=$(basename $LAST_FULL_DIR)
LAST_DATE_FORMATTED=$(echo $LAST_DATE | sed 's/\(....\)\(..\)\(..\)/\1-\2-\3/')
# 计算上次全量备份后的第三天
THREE_DAYS_LATER=$(date -d "$LAST_DATE_FORMATTED + 3 days" +%Y%m%d)
# 如果今天的日期大于或等于上次全量备份后的第三天,则执行全量备份
if (( TODAY >= THREE_DAYS_LATER )); then
# 执行全量备份
FULL_DIR=$FULL_BACKUP_DIR/$TODAY
mkdir -p $FULL_DIR
mariabackup --backup --target-dir=$FULL_DIR --user=$USER --password=$PASSWORD
if [ $? -eq 0 ]; then
echo $FULL_DIR > $LAST_FULL_BACKUP_FILE
else
echo "全量备份失败"
exit 1
fi
else
# 执行增量备份
INC_DIR=$INC_BACKUP_DIR/$TODAY
mkdir -p $INC_DIR
mariabackup --backup --target-dir=$INC_DIR --incremental-basedir=$LAST_FULL_DIR --user=$USER --password=$PASSWORD
if [ $? -ne 0 ]; then
echo "增量备份失败"
exit 1
fi
fi
fi
# 删除七天前的备份文件,确保只保留最近一周的备份
SEVEN_DAYS_AGO=$(date -d "7 days ago" +%Y%m%d)
echo "删除旧备份 older than ${SEVEN_DAYS_AGO}"
# 删除旧的全量备份
for dir in "${FULL_BACKUP_DIR}"/*; do
if [[ -d "${dir}" && $(basename "${dir}") < "${SEVEN_DAYS_AGO}" ]]; then
echo "Deleting ${dir}"
rm -rf "${dir}"
fi
done
# 删除旧的增量备份
for dir in "${INC_BACKUP_DIR}"/*; do
if [[ -d "${dir}" && $(basename "${dir}") < "${SEVEN_DAYS_AGO}" ]]; then
echo "Deleting ${dir}"
rm -rf "${dir}"
fi
done
定时任务
每天凌晨 2:00执行脚本
crontab -e
0 2 * * * /backup/backup.sh
调整时间验证
date -s "2025-04-09 1:59:30"
2、MySQL 8.0的备份与恢复
创建备份目录
mkdir -p /backup/{full,inc}
(1)全量备份 && 恢复
xtrabackup --user=root --password=123@.cOM --backup --parallel=10 --socket=/tmp/mysql.sock --target-dir=/backup/full
全量恢复
#基础准备
xtrabackup --prepare --target-dir=/backup/full/要恢复的时间目录
#停止服务
systemctl stop mysqld
#删除数据目录数据
rm -rf /data/mysql/*
#恢复
xtrabackup --copy-back --target-dir=/backup/full/要恢复的时间目录
#重新给予授权
chown -R mysql.mysql /data/mysql
systemctl restart mysqld
(2)增量备份 && 恢复
xtrabackup --backup -uroot -pGmq224531 --target-dir=/backup/inc --socket=/tmp/mysql.sock --incremental-basedir=/backup/full
增量恢复
#首先,准备基本备份 也就是统一完整备份的时间
xtrabackup --prepare --apply-log-only --target-dir=/全量备份目录
#然后,将增量更改应用于基本完整备份
xtrabackup --prepare --apply-log-only --target-dir=/全量备份目录 --incremental-dir=/增量备份目录
#停止服务
systemctl stop mysqld
#删除数据目录数据
rm -rf /data/mysql/*
#准备全量备份
xtrabackup --prepare --target-dir=/backup/full/要恢复的时间目录
#恢复
xtrabackup --copy-back --target-dir=/backup/full/要恢复的时间目录
#重新给予授权
chown -R mysql.mysql /data/mysql
systemctl restart mysqld
systemctl restart mysqld
(3)自动化备份 && 定时任务
全量备份
#!/bin/bash
#配置环境变量让cron的定时任务可以生效
source /etc/profile
source ~/.bashrc
export PATH=$PATH:/usr/local/bin
# 定义备份目录和用户信息
BACKUP_BASE=/backup
FULL_BACKUP_DIR=$BACKUP_BASE/full
USER=root
PASSWORD=123.com # 注意:建议使用环境变量或配置文件存储密码
SOCK=/tmp/mysql.sock
# 获取今天的日期
TODAY=$(date +"%Y年%m月%d日备份") # 用于目录名和文件名,例如 "2025年04月09日备份"
TODAY_YMD=$(date +"%Y%m%d") # 用于比较日期,例如 "20250409"
# 执行全量备份
FULL_DIR=$FULL_BACKUP_DIR/$TODAY
mkdir -p "$FULL_DIR"
xtrabackup --user=$USER --password=$PASSWORD --backup --parallel=10 --socket=$SOCK --target-dir=$FULL_DIR
# 打包备份目录为 tar.gz 文件
TAR_FILE="$FULL_BACKUP_DIR/${TODAY}.tar.gz"
tar -zcf "$TAR_FILE" -C "$FULL_BACKUP_DIR" "$TODAY"
# 配置 MinIO 别名
mc alias set db http://192.168.100.14:9000 dvdDrcD6VeT25hGhvkaN R7gKVpMDxLy8xrikdWHsHCaaLBAZuiAnAMN8Q2Ke
# 上传 tar.gz 文件到 MinIO
mc cp "$TAR_FILE" db/full-backups/tax/mysql2/"${TODAY}.tar.gz"
# 删除当天的备份目录(只保留 tar.gz 文件)
rm -rf "$FULL_DIR"
# 删除1天前的旧文件(包括旧的 tar.gz 文件)
SEVEN_DAYS_AGO=$(date -d "1 days ago" +%Y%m%d)
echo "删除旧备份 older than ${SEVEN_DAYS_AGO}"
for file in "${FULL_BACKUP_DIR}"/*; do
# 提取文件名中的日期部分(假设文件名格式为 "YYYY年MM月DD日备份.tar.gz")
basename=$(basename "$file")
# 将文件名转换为 YYYYMMDD 格式以便比较
if [[ $basename =~ ([0-9]{4})年([0-9]{2})月([0-9]{2})日备份\.tar\.gz ]]; then
file_date="${BASH_REMATCH[1]}${BASH_REMATCH[2]}${BASH_REMATCH[3]}"
if [[ "$file_date" < "$SEVEN_DAYS_AGO" ]]; then
echo "正在删除旧文件: $file"
rm -f "$file"
fi
fi
done
echo "备份完成,tar 文件已上传至 MinIO: db/full-backups/tax/mysql1/${TODAY}.tar.gz"
全量+增量
#!/bin/bash
#配置环境变量让cron的定时任务可以生效
source /etc/profile
source ~/.bashrc
export PATH=$PATH:/usr/local/bin
# 定义备份目录和用户信息
BACKUP_BASE=/backup
FULL_BACKUP_DIR=$BACKUP_BASE/full
INC_BACKUP_DIR=$BACKUP_BASE/inc
LAST_FULL_BACKUP_FILE=$BACKUP_BASE/last_full_backup.txt
USER=root
PASSWORD=Gmq224531 # 注意:请使用安全的方式存储密码,例如通过环境变量或配置文件
SOCK=/tmp/mysql.sock
#将脚本日志输出到shlog中
exec > /$BACKUP_BASE/shlog.txt 2>&1
# 获取今天的日期(YYYYMMDD格式)
TODAY=$(date +%Y%m%d)
# 如果上次全量备份记录文件不存在,则执行全量备份
if [ ! -f "$LAST_FULL_BACKUP_FILE" ]; then
# 执行全量备份
FULL_DIR=$FULL_BACKUP_DIR/$TODAY
mkdir -p $FULL_DIR
xtrabackup --user=$USER --password=$PASSWORD --backup --parallel=10 --socket=$SOCK --target-dir=$FULL_DIR
if [ $? -eq 0 ]; then
echo $FULL_DIR > $LAST_FULL_BACKUP_FILE
else
echo "全量备份失败"
exit 1
fi
else
# 读取上次全量备份的目录
LAST_FULL_DIR=$(cat $LAST_FULL_BACKUP_FILE)
LAST_DATE=$(basename $LAST_FULL_DIR)
LAST_DATE_FORMATTED=$(echo $LAST_DATE | sed 's/\(....\)\(..\)\(..\)/\1-\2-\3/')
# 计算上次全量备份后的第三天
THREE_DAYS_LATER=$(date -d "$LAST_DATE_FORMATTED + 3 days" +%Y%m%d)
# 如果今天的日期大于或等于上次全量备份后的第三天,则执行全量备份
if (( TODAY >= THREE_DAYS_LATER )); then
# 执行全量备份
FULL_DIR=$FULL_BACKUP_DIR/$TODAY
mkdir -p $FULL_DIR
xtrabackup --user=$USER --password=$PASSWORD --backup --parallel=10 --socket=$SOCK --target-dir=$FULL_DIR
if [ $? -eq 0 ]; then
echo $FULL_DIR > $LAST_FULL_BACKUP_FILE
else
echo "全量备份失败"
exit 1
fi
else
# 执行增量备份
INC_DIR=$INC_BACKUP_DIR/$TODAY
mkdir -p $INC_DIR
xtrabackup --backup -u$USER -p$PASSWORD --target-dir=$INC_DIR --socket=$SOCK --incremental-basedir=$LAST_FULL_DIR
if [ $? -ne 0 ]; then
echo "增量备份失败"
exit 1
fi
fi
fi
# 删除七天前的备份文件,确保只保留最近一周的备份
SEVEN_DAYS_AGO=$(date -d "7 days ago" +%Y%m%d)
echo "删除旧备份 older than ${SEVEN_DAYS_AGO}"
# 删除旧的全量备份
for dir in "${FULL_BACKUP_DIR}"/*; do
if [[ -d "${dir}" && $(basename "${dir}") < "${SEVEN_DAYS_AGO}" ]]; then
echo "Deleting ${dir}"
rm -rf "${dir}"
fi
done
# 删除旧的增量备份
for dir in "${INC_BACKUP_DIR}"/*; do
if [[ -d "${dir}" && $(basename "${dir}") < "${SEVEN_DAYS_AGO}" ]]; then
echo "Deleting ${dir}"
rm -rf "${dir}"
fi
done
定时任务
每天凌晨 2:00执行脚本
crontab -e
0 2 * * * /backup/backup.sh
调整时间验证
date -s "2025-04-09 1:59:55"
3、MySQL 5.7的备份与恢复MySQL 8.0的备份与恢复
创建备份目录
mkdir -p /backup/{full,inc}
(1)全量备份 && 恢复
xtrabackup --user=root --password=123.com --backup --parallel=10 --socket=/tmp/mysql.sock --target-dir=/backup/full
全量恢复
#基础准备
xtrabackup --prepare --target-dir=/backup/full/要恢复的时间目录
#停止服务
systemctl stop mysql
#删除数据目录数据
rm -rf /data/mysql/*
#恢复
xtrabackup --copy-back --target-dir=/backup/full/要恢复的时间目录
#重新给予授权
chown -R mysql.mysql /data/mysql
systemctl restart mysql
(2)增量备份 && 恢复
xtrabackup --backup -uroot -pGmq224531 --target-dir=/backup/inc --socket=/tmp/mysql.sock --incremental-basedir=/backup/full
增量恢复
#首先,准备基本备份 也就是统一完整备份的时间
xtrabackup --prepare --apply-log-only --target-dir=/全量备份目录
#然后,将增量更改应用于基本完整备份
xtrabackup --prepare --apply-log-only --target-dir=/全量备份目录 --incremental-dir=/增量备份目录
# 合并第2次增量备份到完全备份,最后一次备份的还原不需要加选项--apply-log-only (如果有的话) ###
# xtrabackup --prepare --target-dir=/backup/base --incremental-dir=/backup/inc2 ###
#停止服务
systemctl stop mysql
#删除数据目录数据
rm -rf /data/mysql/*
#恢复
xtrabackup --copy-back --target-dir=/backup/full/要恢复的时间目录
#重新给予授权
chown -R mysql.mysql /data/mysql
systemctl restart mysql
systemctl restart mysql
(3)自动化备份 && 定时任务
全量备份
#!/bin/bash
#配置环境变量让cron的定时任务可以生效
source /etc/profile
source ~/.bashrc
export PATH=$PATH:/usr/local/bin
# 定义备份目录和用户信息
BACKUP_BASE=/backup
FULL_BACKUP_DIR=$BACKUP_BASE/full
USER=root
PASSWORD=Gmq224531 # 注意:建议使用环境变量或配置文件存储密码
SOCK=/tmp/mysql.sock
# 获取今天的日期
TODAY=$(date +"%Y年%m月%d日备份") # 用于目录名和文件名,例如 "2025年04月09日备份"
TODAY_YMD=$(date +"%Y%m%d") # 用于比较日期,例如 "20250409"
# 执行全量备份
FULL_DIR=$FULL_BACKUP_DIR/$TODAY
mkdir -p "$FULL_DIR"
xtrabackup --user=$USER --password=$PASSWORD --backup --parallel=10 --socket=$SOCK --target-dir=$FULL_DIR
# 打包备份目录为 tar.gz 文件
TAR_FILE="$FULL_BACKUP_DIR/${TODAY}.tar.gz"
tar -zcf "$TAR_FILE" -C "$FULL_BACKUP_DIR" "$TODAY"
# 配置 MinIO 别名
mc alias set db http://192.168.100.14:9000 dvdDrcD6VeT25hGhvkaN R7gKVpMDxLy8xrikdWHsHCaaLBAZuiAnAMN8Q2Ke
# 上传 tar.gz 文件到 MinIO
mc cp "$TAR_FILE" db/full-backups/tax/mysql3/"${TODAY}.tar.gz"
# 删除当天的备份目录(只保留 tar.gz 文件)
rm -rf "$FULL_DIR"
# 删除1天前的旧文件(包括旧的 tar.gz 文件)
SEVEN_DAYS_AGO=$(date -d "1 days ago" +%Y%m%d)
echo "删除旧备份 older than ${SEVEN_DAYS_AGO}"
for file in "${FULL_BACKUP_DIR}"/*; do
# 提取文件名中的日期部分(假设文件名格式为 "YYYY年MM月DD日备份.tar.gz")
basename=$(basename "$file")
# 将文件名转换为 YYYYMMDD 格式以便比较
if [[ $basename =~ ([0-9]{4})年([0-9]{2})月([0-9]{2})日备份\.tar\.gz ]]; then
file_date="${BASH_REMATCH[1]}${BASH_REMATCH[2]}${BASH_REMATCH[3]}"
if [[ "$file_date" < "$SEVEN_DAYS_AGO" ]]; then
echo "正在删除旧文件: $file"
rm -f "$file"
fi
fi
done
echo "备份完成,tar 文件已上传至 MinIO: db/full-backups/tax/mysql1/${TODAY}.tar.gz"
全量备份+增量备份
#!/bin/bash
#配置环境变量让cron的定时任务可以生效
source /etc/profile
source ~/.bashrc
export PATH=$PATH:/usr/local/bin
# 定义备份目录和用户信息
BACKUP_BASE=/backup
FULL_BACKUP_DIR=$BACKUP_BASE/full
INC_BACKUP_DIR=$BACKUP_BASE/inc
LAST_FULL_BACKUP_FILE=$BACKUP_BASE/last_full_backup.txt
USER=root
PASSWORD=Gmq224531 # 注意:请使用安全的方式存储密码,例如通过环境变量或配置文件
SOCK=/tmp/mysql.sock
#将脚本日志输出到shlog中
exec > /$BACKUP_BASE/shlog.txt 2>&1
# 获取今天的日期(YYYYMMDD格式)
TODAY=$(date +%Y%m%d)
# 如果上次全量备份记录文件不存在,则执行全量备份
if [ ! -f "$LAST_FULL_BACKUP_FILE" ]; then
# 执行全量备份
FULL_DIR=$FULL_BACKUP_DIR/$TODAY
mkdir -p $FULL_DIR
xtrabackup --user=$USER --password=$PASSWORD --backup --parallel=10 --socket=$SOCK --target-dir=$FULL_DIR
if [ $? -eq 0 ]; then
echo $FULL_DIR > $LAST_FULL_BACKUP_FILE
else
echo "全量备份失败"
exit 1
fi
else
# 读取上次全量备份的目录
LAST_FULL_DIR=$(cat $LAST_FULL_BACKUP_FILE)
LAST_DATE=$(basename $LAST_FULL_DIR)
LAST_DATE_FORMATTED=$(echo $LAST_DATE | sed 's/\(....\)\(..\)\(..\)/\1-\2-\3/')
# 计算上次全量备份后的第三天
THREE_DAYS_LATER=$(date -d "$LAST_DATE_FORMATTED + 3 days" +%Y%m%d)
# 如果今天的日期大于或等于上次全量备份后的第三天,则执行全量备份
if (( TODAY >= THREE_DAYS_LATER )); then
# 执行全量备份
FULL_DIR=$FULL_BACKUP_DIR/$TODAY
mkdir -p $FULL_DIR
xtrabackup --user=$USER --password=$PASSWORD --backup --parallel=10 --socket=$SOCK --target-dir=$FULL_DIR
if [ $? -eq 0 ]; then
echo $FULL_DIR > $LAST_FULL_BACKUP_FILE
else
echo "全量备份失败"
exit 1
fi
else
# 执行增量备份
INC_DIR=$INC_BACKUP_DIR/$TODAY
mkdir -p $INC_DIR
xtrabackup --backup -u$USER -p$PASSWORD --target-dir=$INC_DIR --socket=$SOCK --incremental-basedir=$LAST_FULL_DIR
if [ $? -ne 0 ]; then
echo "增量备份失败"
exit 1
fi
fi
fi
# 删除七天前的备份文件,确保只保留最近一周的备份
SEVEN_DAYS_AGO=$(date -d "7 days ago" +%Y%m%d)
echo "删除旧备份 older than ${SEVEN_DAYS_AGO}"
# 删除旧的全量备份
for dir in "${FULL_BACKUP_DIR}"/*; do
if [[ -d "${dir}" && $(basename "${dir}") < "${SEVEN_DAYS_AGO}" ]]; then
echo "Deleting ${dir}"
rm -rf "${dir}"
fi
done
# 删除旧的增量备份
for dir in "${INC_BACKUP_DIR}"/*; do
if [[ -d "${dir}" && $(basename "${dir}") < "${SEVEN_DAYS_AGO}" ]]; then
echo "Deleting ${dir}"
rm -rf "${dir}"
fi
done
定时任务
每天凌晨 2:00执行脚本
crontab -e
0 2 * * * /backup/backup.sh
调整时间验证
date -s "2025-04-09 1:59:55"
四、将全量备份推送到minio
为数据库服务器安装mc
wget https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc
sudo mv mc /usr/local/sbin/
保证服务器的时区同步
验证minio
mc alias set <别名> <MinIO URL> <访问密钥> <秘密密钥>
例如
mc alias set db http://192.168.100.14:9000 dvdDrcD6VeT25hGhvkaN R7gKVpMDxLy8xrikdWHsHCaaLBAZuiAnAMN8Q2Ke
将目录推送到minio
mc cp --recursive /backup/full/20250410/ db/full-backups/20250410
五、本地空间不足的流式传输或者(zstd内建压缩)
本地空间不足,备份下来的数据量大于本地磁盘则备份会出错,那这里有两个解决办法
要么用zstd的压缩备份 即备份下来就是压缩好的(效率很高)
要么就用流式传输的选项将备份直接推送到minio(吃带宽,效率慢)
我个人更推崇zstd他效率高且不备份.bin
1、zstd压缩备份
在mariadb-backup中10.5本身是不支持zstd的,10.6之上才支持,所以我这里采用外装zstd用管道符去引导数据
#安装zstd压缩工具
yum -y install epel-release
yum -y install zstd
zstd脚本
#!/bin/bash
BACKUP_BASE=/backup
FULL_BACKUP_DIR=$BACKUP_BASE/full
DATA_DIR=/backup/data # 明确定义 data 目录变量
LOG_FILE="$BACKUP_BASE/log/shlog_$(date +%Y%m%d).txt" # 每天一个日志文件
# 将脚本日志输出到shlog中 (推荐启用)
exec > "$LOG_FILE" 2>&1
# 配置环境变量让cron的定时任务可以生效
source /etc/profile > /dev/null 2>&1 # 避免 profile 输出干扰
source ~/.bashrc > /dev/null 2>&1 # 避免 bashrc 输出干扰
export PATH=$PATH:/usr/local/sbin # 确保 zstd, mc 等命令在 PATH 中
# 定义备份目录和用户信息
USER=backup
PASSWORD='xxxxxxxxx7=8*' # 密码已用单引号保护
# 创建必要的目录 (如果不存在)
mkdir -p "$FULL_BACKUP_DIR"
mkdir -p "$DATA_DIR"
echo "脚本开始于: $(date)"
# 获取本地IP地址
LOCAL_IP=$(ip addr show eth0 | grep -oP 'inet \K[\d.]+' | head -1)
if [ -z "$LOCAL_IP" ]; then
echo "无法从 eth0 获取 IP,尝试 hostname -I"
LOCAL_IP=$(hostname -I | awk '{print $1}')
fi
if [ -z "$LOCAL_IP" ]; then
echo "错误:无法获取本地 IP 地址。"
exit 1
fi
echo "获取到本地 IP: $LOCAL_IP"
# 获取今天的日期
TODAY=$(date +"%Y%m%d")
echo "备份日期: $TODAY"
# 备份文件名
BACKUP_FILE="$FULL_BACKUP_DIR/$LOCAL_IP-$TODAY.mbstream.zst"
echo "备份文件将是: $BACKUP_FILE"
# 备份数据库
echo "开始备份数据库..."
mariadb-backup --backup --user=$USER --password=$PASSWORD --stream=mbstream --target-dir="$DATA_DIR" | zstd > "$BACKUP_FILE"
# 检查备份和压缩是否成功
if [ "${PIPESTATUS[0]}" { -ne 0 ] || [ ${PIPESTATUS[1]} -ne 0 ]; then
echo "错误:mariadb-backup 或 zstd 执行失败。"
echo "mariadb-backup 退出码: ${PIPESTATUS[0]}"
echo "zstd 退出码: ${PIPESTATUS[1]}"
# 可以考虑删除可能产生的损坏的备份文件
rm -f "$BACKUP_FILE"
exit 1
fi
echo "数据库备份和压缩成功完成。本地文件: $BACKUP_FILE"
# 配置 MinIO 别名 (建议:如果别名固定,可以在脚本外部设置一次,脚本内检查是否存在即可)
echo "设置/检查 MinIO 别名..."
mc alias set db https://ilaw-io.crec.cn w9WxxxxxxxxxxxRE8gkip qbibSRBCcMMg0xxxxxxxxxxx2VpsR
if [ $? -ne 0 ]; then
# 如果设置失败,可能已存在或有其他问题,尝试继续,但记录警告
echo "警告:mc alias set 命令执行可能存在问题 (错误码 $?), 尝试继续上传..."
fi
# 上传到 MinIO
MINIO_PATH="db/mariadb-backup/order/$LOCAL_IP/$LOCAL_IP-$TODAY.mbstream.zst"
echo "开始上传到 MinIO: $MINIO_PATH ..."
mc cp "$BACKUP_FILE" "$MINIO_PATH"
# 检查上传是否成功
if [ $? -ne 0 ]; then
echo "错误:上传到 MinIO 失败。"
# 根据策略决定是否退出或继续执行删除本地旧备份
# exit 1 # 如果上传失败则不删除本地旧文件,可以选择退出
else
echo "上传成功,已将备份数据推送到 MinIO。"
# 上传成功后,删除本地超过1天的旧备份
echo "开始删除本地旧备份 (保留当天)..."
find "$FULL_BACKUP_DIR" -maxdepth 1 -type f -name "$LOCAL_IP-*.mbstream.zst" -mtime +0 -delete
if [ $? -ne 0 ]; then
echo "警告:删除本地旧备份时遇到问题。"
else
echo "旧备份删除完成。"
fi
fi
echo "脚本结束于: $(date)"
exit 0
2、流式传输
直接将数据推送到MinIO中
#!/bin/bash
#配置环境变量让cron的定时任务可以生效
source /etc/profile
source ~/.bashrc
export PATH=$PATH:/usr/local/sbin
# 定义备份目录和用户信息
USER=root
PASSWORD=mimi
#获取本地IP地址
LOCAL_IP=$(ip addr show eth0 | grep -oP 'inet \K[\d.]+' | head -1)
if [ -z "$LOCAL_IP" ]; then
LOCAL_IP=$(hostname -I | awk '{print $1}') # 如果 eth0 失败,使用 hostname 获取
fi
# 获取今天的日期
TODAY=$(date +"%Y%m%d") # 用于目录名和文件名
# 配置 MinIO 别名 && 数据流式传输到minio
mc alias set db https://xxxxxxxxx.cn 12345678896MVsdRE8gkip 12345678896bSRBCcM12345678896GGKt12345678896
mariabackup --backup --stream=xbstream --parallel=20 --user="$USER" --password="$PASSWORD" | mc pipe db/mariadb-backup/tax/"$LOCAL_IP"-"$TODAY".xbstream
echo "上传完成 已将备份数据推送到minIO"
六、从MinIO获取备份文件并恢复(全量)
安装mc:
wget https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc
sudo mv mc /usr/local/sbin/
1、获取流式文件并解压
获取流式文件并解压为目录(mariadb-bakcup为mbstream、Xtrabackup为xbstream,注意更改文件备份的后缀)
mc get db/mariadb-backup/order/10.81.107.129/20250411.mbstream /backup
mbstream -x -v -C /backup/full < /backup/20250411.mbstream
#在从备份还原之前,您首先需要准备备份以使数据文件一致
mariadb-backup --prepare --target-dir=/备份目录
#还原备份(数据目录必须保持为空)
rm -rf /数据目录
mariadb-backup --copy-back --target-dir=/备份目录
#重新给予数据目录权限
chown -R mysql:mysql /数据目录
#重新启动服务
systemctl restart mariadb
2、获取tar并解压
获取tar.gz包并解压
mc get db/mariadb-backup/dev/10.81.15.164/20250410.tar.gz /backup
tar -zxvf 20250410.tar.gz
#在从备份还原之前,您首先需要准备备份以使数据文件一致
mariadb-backup --prepare --target-dir=/备份目录
#还原备份(数据目录必须保持为空)
rm -rf /数据目录
mariadb-backup --copy-back --target-dir=/备份目录
#重新给予数据目录权限
chown -R mysql:mysql /数据目录
#重新启动服务
systemctl restart mariadb
3、获取zst并解压
zstdcat /压缩文件路径 | mbstream -x -C /恢复到哪里的路径
#在从备份还原之前,您首先需要准备备份以使数据文件一致
mariadb-backup --prepare --target-dir=/备份目录
#还原备份(数据目录必须保持为空)
rm -rf /数据目录
mariadb-backup --copy-back --target-dir=/备份目录
#重新给予数据目录权限
chown -R mysql:mysql /数据目录
#重新启动服务
systemctl restart mariadb