本文最后更新于 2024-07-06,文章内容可能已经过时。

因为昨天操作失误把数据库清空了,虽然使用binlog日志重新恢复了数据库,但是因为服务器是甲骨文,随时有可能会被删机,被删机可就真的没救了,所以还是弄一下数据库云端备份了。

Shell 定时备份MySQL数据库上传到七牛云存储桶,参考资料来源于网上

安装和配置qshell

  1. 下载qshell

官方发布页:github,可以参考README.MD资料

# 先到工作目录下面进行操作,不建议将文件到处放
cd /data/soft/qshell
# 下载最新版本的可执行程序,需要对应系统
wget https://github.com/qiniu/qshell/releases/download/v2.9.0/qshell-v2.9.0-linux-arm64.tar.gz
tar -zxvf qshell-v2.9.0-linux-arm64.tar.gz
rm -rf qshell-v2.9.0-linux-arm64.tar.gz

解压出来的qshell自带可执行权限,不需要单独进行设置,环境变量可以根据需要进行设置,我不设置了(懒)。

  1. 配置qshell

访问个人中心 -> 密钥管理页面获取AS/SK

# 添加七牛云账号
qshell account 你的AK 你的SK 设置一个名字
# 显示用户账号列表
qshell user ls

配置备份脚本

我把脚本放到了/data/script/mysql_data_backup.sh

#!/usr/bin/env bash
# Function description:
# Backup MySQL databases for each, backup schema and schema with data in one action.

# Usage:
# bash mysql_bash_backup.sh

# Every friday night execute
# 58 23 * * 5 /usr/local/mysql/script/mysql_data_backup.sh >/tmp/log_backup_mysql_$(date +"\%Y\%m\%d\%H\%M\%S").log

USER="`id -un`"
LOGNAME="$USER"
if [ $UID -ne 0 ]; then
    echo "WARNING: Running as a non-root user, \"$LOGNAME\". Functionality may be unavailable. Only root can use some commands or options"
fi

old_PATH=$PATH
declare -x PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"

mysql_host=127.0.0.1                  # 数据库地址  
mysql_port=3306                       # 数据库端口 
mysql_username=root                   # 数据库用户名  
mysql_password=root                   # 数据库密码
save_old_backups_for_days=13          # 保留备份多少时间  
mysql_bin_mysql=/usr/bin/mysql        # mysql可执行程序的地址  
mysql_bin_dump=/usr/bin/mysqldump     # mysqldump可执行程序的地址  
mysql_datadir=/var/lib/mysql          # mysql数据目录地址  
mysql_backup_dir=/data/backup/mysql   # mysql数据备份地址  
password=123456                       # 备份压缩包密码
qshell=/data/soft/qshell/qshell       # qshell可执行程序地址  
bucket=xxxxxx                         # 七牛云bucket名称   
bucket_dir=backup/mysql               # 七牛云上传文件的前缀路径 


date_format_type_dir=$(date '+%Y%m%d%H%M%S')

echo "--------------------------------"
echo "=> do backup scheduler start at $(date +%Y%m%d%H%M%S)"

[ -x ${mysql_bin_mysql} ] || mysql_bin_mysql=mysql
[ -x ${mysql_bin_dump} ] || mysql_bin_dump=mysqldump
[ -d ${mysql_backup_dir}/${date_format_type_dir} ] || mkdir -p ${mysql_backup_dir}/${date_format_type_dir}

mysql_databases_list=""
if [ -d ${mysql_datadir} ]; then
    mysql_databases_list=`ls -p ${mysql_datadir} | grep / |tr -d /`
else
    mysql_databases_list=$(${mysql_bin_mysql} -h${mysql_host} -P${mysql_port} -u${mysql_username} -p${mysql_password} -e "show databases;" )
fi

saved_IFS=$IFS
IFS=' '$'\t'$'\n'
for mysql_database in ${mysql_databases_list};do
    if echo ${mysql_database} | grep -Eqvi "^database$|sys|information_schema|performance_schema|#innodb_redo|#innodb_temp|^mysql$" ; then
      ${mysql_bin_dump} -u${mysql_username} -p${mysql_password} --host=${mysql_host} --port=${mysql_port}\
          --routines --events --triggers --single-transaction --flush-logs \
          --ignore-table=mysql.event --databases ${mysql_database} |& \
          gzip > ${mysql_backup_dir}/${date_format_type_dir}/${mysql_database}.sql.gz

      [ $? -eq 0 ] && echo "${mysql_database} backup successfully! " || \
          echo "${mysql_database} backup failed! "
      /bin/sleep 2

      ${mysql_bin_dump} -u${mysql_username} -p${mysql_password} --host=${mysql_host} --port=${mysql_port}\
           --routines --events --triggers --single-transaction --flush-logs \
           --ignore-table=mysql.event --databases ${mysql_database} --no-data |& \
           gzip > ${mysql_backup_dir}/${date_format_type_dir}/${mysql_database}_schema.sql.gz

      [ $? -eq 0 ] && echo "${mysql_database} schema backup successfully! " || \
          echo "${mysql_database} schema backup failed! "
      /bin/sleep 2
    fi
done
IFS=${saved_IFS}

save_days=${save_old_backups_for_days:-10}
need_clean=$(find ${mysql_backup_dir} -mtime +${save_days} -exec ls '{}' \;)
    if [ ! -z "${need_clean}" ]; then
        find ${mysql_backup_dir} -mtime +${save_days} -exec rm -rf '{}' \;
        echo "$need_clean have been cleaned! "
    else
        echo "nothing can be cleaned, skipped! "
    fi

echo "=> do backup scheduler finished at $(date +%Y%m%d%H%M%S)"
echo -e "\n\n\n"

#上传七牛start
echo ${mysql_backup_dir}/${date_format_type_dir} "\n\n\n" ccc "\n\n\n"
if [ -d ${mysql_backup_dir}/${date_format_type_dir} ]; then
   cd ${mysql_backup_dir}
   zipFile="${mysql_backup_dir}/mysql_${date_format_type_dir}.zip"
   zip -rP "${password}"  ${zipFile} ${date_format_type_dir}
   ${qshell} rput ${bucket} "${bucket_dir}/mysql_qn_${date_format_type_dir}.zip" ${zipFile} && rm -f ${zipFile}
fi
#上传七牛over
declare -x PATH=${old_PATH}

脚本我随便修改了一下,将常用配置放到了一起,主要需要修改对应的变量 20行-32行:

image-20220828033307626

添加执行权限并且手动执行一次进行测试

chmod +x mysql_data_backup.sh
./mysql_data_backup.sh

添加定时任务

肯定不可能每次都去手动执行脚本去进行备份的,所以我们需要新增一个定时任务,使用 crontab

# 为当前用户添加定时任务,也可以手动修改/etc/crontab设置全用户的定时任务
crontab -e

# 将以下代码复制到最下面一行
# 每日凌晨执行备份脚本,并且将脚本日志写入到/data/logs/backup_mysql目录下
0 0 * * * /data/script/mysql_data_backup.sh >/data/logs/backup_mysql/log_backup_mysql_$(date +"\%Y\%m\%d\%H\%M\%S").log

效果

image-20220828034536832

image-20220828034836865