MySQL备份脚本+邮件告警通知
如标题,大概干了这么一件事
角色划分
机器 | 角色 | 脚本 | 计划任务 | 操作系统 | 版本信息 |
---|---|---|---|---|---|
机器A | MySQL节点 | MySQL备份 | 07 2 * * * | Ubuntu 20.04 | MySQL Ver 8.0.29 for Linux on x86_64 mysqldump Ver 8.0.29-0ubuntu0.20.04.3 |
机器B | 异机备份节点 | 异机备份情况检查 | 15 3 * * * | Debian 10.9 | |
机器C | 邮件告警节点 | MySQL备份情况邮件发送 | 无 | CentOS 8.5.2111 |
话不多说先上MySQL备份的脚本,脚本并不复杂(其实看了有一些脚本 不过shell来写,还都是用mysqldump的 流程其实都大差不差,关键是mysqldump的参数_不过用mysqldump来备份的 想来应该不会是大型又很复杂的环境)
之前手动模拟的时候出现过mysqldump卡住的情况,然后稍微研究了下mysqldump的参数,自认为当前这样的组合 稍微较为全些,也不会出现锁表的情况
-R -E --skip-lock-tables
--skip-lock-table, 不锁表
-R, 备份存储程序(过程和函数)
-E, 备份事件表
--single-transaction, 一致性备份、 InnoDB类型的锁行
–single-transaction 这个参数现在还是拿捏不住 之前有查过一些说是「一致性备份、 InnoDB类型的锁行」,如果是锁行,那是否会一直影响卡住嘛? 不会执行一晚上然后 一直卡着吧 有点恐怖)
有点放心不下,所以又增加了邮件告警通知 以防真卡住的时候 还能知晓下然后手动处理
至于脚本中其他几个参数,是否可以这样结合,是否理解正确,从本弱鸡所查到的和理解的 应该是这样,现在不过也只是了解一些皮毛,如果有所误导还请多多指正,感谢感谢🙏🙏
#!/bin/bash
# Author: zhb
# Time: 2022-07-18 2:15
# 备份流程: 1.全库or指定库备份(文件直接压缩成 .gz) -> 2.异机拷贝 -> 3.删除历史备份文件(仅删除.gz即可) | 逻辑备份
# 优化,相比V1.3 去除压缩部分,直接在备份时生成压缩包
# Version: V1.4
# crontab -> 33 2 * * * /beta/mysql_backup/scripts/mysql_backup.sh >> /beta/mysql_backup/scripts/mysql_backup.info.log 2 >> /beta/mysql_backup/scripts/mysql_backup.err.log
set -x
MYSQL_USER=root
MYSQL_PASSWORD=<密码>
MYSQL_HOST=<MySQL节点IP地址>
MYSQL_PORT=3306
DB_BACKUP_PATH=/beta/mysql_backup
BAK_GZ=mysql_bak_$(date +%F-%H%M).sql.gz
#备份文件保存天数 (异机备份的文件默认不做删除-机器B)
KEEP_DAYS=10
#指定备份的数据库,可以指定多个中间用空格隔开
BAK_DATABASES=("mysql" "apolloportaldb" "apolloconfigdb_fat")
# 开始执行备份
echo "--------$(date +%F_%T) Start MySQL Database Backup--------" >> ${DB_BACKUP_PATH}/backup.log
# V1,指定数据库备份
# for database in "${BAK_DATABASES[@]}"
# do
# mysqldump -u${MYSQL_USER} -p${MYSQL_PASSWORD} --host=${MYSQL_HOST} --port=${MYSQL_PORT} --databases $database -R -E --skip-lock-tables --single-transaction | gzip > ${DB_BACKUP_PATH}/${BAK_GZ}
# done
# V2,备份所有库 (V1指定部分数据库 V2全库备份 2选1)
mysqldump -u$MYSQL_USER -p$MYSQL_PASSWORD -h$MYSQL_HOST -P$MYSQL_PORT --all-databases -R -E --skip-lock-tables --single-transaction | gzip > $DB_BACKUP_PATH/$BAK_GZ
# 异机拷贝
if [ -f $DB_BACKUP_PATH/$BAK_GZ ]; then
scp $DB_BACKUP_PATH/$BAK_GZ root@机器B的IP:/机器B的存储目录
else
echo "异机拷贝失败,找不到备份文件"
exit 1
fi
# 删除历史备份文件「10天」
find $DB_BACKUP_PATH -mtime +$KEEP_DAYS -type f -name 'mysql_bak_*.sql.gz' -exec rm -rf {} \;
# 结束备份
echo "--------$(date +%F_%T) Stop MySQL Database Backup--------" >> ${DB_BACKUP_PATH}/backup.log
###### 备份文件情况:备份完成后,会出现1个xxx.sql.gz的压缩文件
# 由于对 gzip和gunzip在工作中用的比较少,但是又想实现直接压缩成.sql.gz 省却压缩的步骤,就也研究了下 算是回顾了
# 解压(原文件会默认删除),gunzip xxx.sql.gz | 会解压出xxx.sql
# 解压时保存原文件,gunzip -k xxx.sql.gz
# 压缩文件(原文件会默认删除),gzip xxx.sql | 会压缩出 xxx.sql.gz
# 压缩时保存原文件(通过控制台输出重定向,如果文件大应该会比较慢),gzip -c xxx-2.sql > xxx-2.sql.gz
# 查看压缩文件,gunzip或gzip -l xxx.sql.gz
###### 脚本中mysqldump使用参数解释 【准确参数最好还是参考官网,以下仅供参考】
# --skip-lock-table 不锁表
# -R 备份存储程序(过程和函数) Dump stored routines (functions and procedures)
# -E, --events 备份事件表 Dump events
# --single-transaction 一致性备份,锁行 # MyISAM为锁表 --lock-all-tables | InnoDB为锁行 --single-transaction
# --triggers 备份触发器(默认备份,所以可以不用带)
执行完成后
生成一个备份.sql.gz 在机器B 中也同样存在
异机备份检查-机器B
########### 机器B 异机备份检查###########
#机器B: 检查机器A->机器B是否完成异机备份,并邮箱发送备份情况
vim /mnt/sda1/mysql_backup/scripts/mysql_backup_check.sh
#!/bin/bash
#Author: zhb
#Time: 2022.07.18 3:30
#crontab -> 40 3 * * * /mnt/sda1/mysql_backup/scripts/mysql_backup_check.sh >> /mnt/sda1/mysql_backup/scripts/mysql_backup_check_info.log 2>> /mnt/sda1/mysql_backup/scripts/mysql_backup_check_error.log
# 此处放宽匹配条件,只要有当天的备份即可-凌晨跑的任务,所以判断时只会有最新传进来的数据
BACKUP_TIME=mysql_bak_`date "+%Y-%m-%d"`
BACKUP_PATH=/mnt/sda1/mysql_backup
ALERT_SCRIPT=/home/send_mail/DEV_QA_send_mail.sh
# 因为机器B的mailx邮件发送有问题,所以找了机器C这台CentOS机器来做邮件发送
if [ `ls $BACKUP_PATH | grep $BACKUP_TIME | wc -l ` -eq 1 ];then
ssh 机器C 'sh /home/send_mail/DEV_QA_send_mail.sh 1'
else
ssh 机器C 'sh /home/send_mail/DEV_QA_send_mail.sh 2'
fi
小插曲:Ubuntu 设置crontab
sudo select-editor # 选择vim作为编辑器(nano咱确实不会用)
添加规则
reload生效, 根据历史经验centos下不用reload,ubuntu下却用
sudo service cron reload
邮件告警通知节点-机器C
需要提前配置mailx -> 发件人、收件人 可参考通过mailx实现邮件告警
# 邮箱发送脚本,具体实现邮件通知备份成功或失败 | 本来想也放到机器B上 直接整好邮件发送,可惜是Ubuntu系统 之前没在上边跑过邮件发送,所以就省事直接切在CentOS上机器上了
vim /home/send_mail/DEV_QA_send_mail.sh
#!/bin/bash
#Author: zhb
#Time: 2022.07.18 2:00
# 根据备份情况,两种不同的主题和内容
content1=$(echo "MySQL备份完成!")
content2=$(echo "MySQL备份异常,请检查任务!")
if [[ $1 = 1 ]];then
echo ${content1} | mail -s "DEV_QA_MySQL_备份监控" beta_monitor@163.com
else
echo ${content2} | mail -s "DEV_QA_MySQL_备份监控" beta_monitor@163.com
fi
可以手动测试邮件是否能发出去
echo ”测试邮件“ | mail -s "DEV_QA_MySQL_备份监控" beta_monitor@163.com
Debain 里的情况不太清楚 | 我看 postfix 服务在启动,应该还是要配置的,与centos中的/etc/mail.rc不同,后边碰到再研究吧
报错:Undelivered Mail Returned to Sender)
效果图
参考和其他
mysqldump实现增量备份,暂时没试过
https://blog.51cto.com/myhwj/1889420
cron服务重启生效的文章介绍,https://www.codenong.com/10193788/
gzip参考,https://www.cnblogs.com/xzlive/p/12673495.html
gunzip参考,https://www.runoob.com/linux/linux-comm-gunzip.html
mysql备份脚本-gzip直接压缩那段,https://cloud.tencent.com/developer/article/1333859
https://www.sky8g.com/technology/3089/
对了,mysql8 和 mysqldump5.7 貌似要改东西,有坑我就先不踩了
还是晚上安安静静好😂😂