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。

https://www.percona.com/blog/aligning-percona-xtrabackup-versions-with-percona-server-for-mysql/?_gl=1*1487djl*_gcl_au*MTE2MjEyMTQxNy4xNjkzNTQ5MDI0
目前 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-backupPercona XtraBackup 的一个分支,增加了对 MariaDB 10.1 压缩静态数据加密的支持。它包含在 MariaDB 10.1.23 及更高版本中。

考虑到大量数据库部署需求,我这里将实验步骤分为:

1、单端控制(使用ansible批量部署软件,运行本地备份以及远端备份的脚本,配置定时任务,xtrabackup innobackupex)

2、使用脚本批量控制数据库运行(如若不然,就需要一台台配置并且每台都做定时任务,后续维护不易寻找目标)

3、配置备份存储服务器(XtraBackup本身就自带远端备份的功能规划好空间和目录就可以)

数据走向:

数据库——backup——>本地(全量增量)——>Minio(全量)

总结:

Mysql使用XtraBackup备份(区分版本),Mariadb使用Mariadb备份。

现版本汇总:

数据库

版本

支持工具

工具版本

Mariadb

10.5.x

MariaDB-backup

10.5.x

Mariadb

10.6.x

MariaDB-backup

10.6.x

Mysql

5.7.x

XtraBackup

2.4.x

Mysql

8.0.x

XtraBackup

8.0.x

100台服务器通过 ansible 控制多个组 以版本为分组其中:

Mariadb备份命令恢复命令相同 并且Mariadb-backup无需单独下载软件包,使用yum就可以下载到yum源配套版本

Mysql 需要区分两个版本其中5.78.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

Mariabackup概述 - MariaDB知識庫

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


Mysql/MariaDB物理备份及MinIO存储—全栈教程
https://www.gmqgmq.cn//archives/SQL-BACKUP
作者
啊耿不累
发布于
2025年04月07日
许可协议