Jichen

Back

MySQL数据冷备+邮件推送提醒Blur image

一、实现步骤说明#

  1. 备份准备阶段
  • 设置数据库连接信息(数据库名、用户名、密码)
  • 配置备份文件存储路径和日志文件路径
  • 检查并创建必要的目录结构
  1. 数据库备份阶段
  • 使用mysqldump执行完整数据库导出
  • 自动记录备份开始和结束时间到日志文件
  • 将SQL文件压缩为tar.gz格式以节省空间
  1. 清理旧备份阶段
  • 自动删除30天前的旧备份文件
  • 保留最新的备份文件
  1. 邮件通知阶段
  • 检查备份结果(成功/失败)
  • 计算最佳通知时间(当天或次日9点)
  • 发送格式化邮件通知,附带备份状态和日志

二、环境准备#

1.安装依赖#

# CentOS/RHEL
sudo yum install mailx

# CentOS/RHEL 8 及以上
sudo yum install s-nail

# Ubuntu/Debian
sudo apt install heirloom-mailx
sh

2,目录结构示例#

/home/dbback/
├── sqlzip/          # 备份存储(700权限)
├── log/             # 日志目录(755权限)
└── dbbackshell/     # 脚本目录(750权限)
sh

3.定时任务配置#

# 编辑当前用户的定时任务列表
crontab -e

# 添加定时任务, 每天凌晨1点执行备份
0 1 * * * /home/dbback/dbbackshell/poetize_db_backup.sh
sh

三、脚本代码实现#

1. 备份主脚本(poetize_db_backup.sh)#

#!/bin/bash

# 定义有备份的数据库名
dbname=poetize
# 定义备份数据库时使用的用户名和密码
dbuser=root
dbpasswd=********
# 数据库备份的路径
backuppath=/home/dbback/sqlzip/
# 数据库备份日志文件存储的路径
logfile=/home/dbback/log/poetize_db_backup.log
# 邮件通知脚本路径
email_script=/home/dbback/dbbackshell/send_backup_email.sh
# 获取当前日期, 以当前的时间作为备份的数据库命名
Now=$(date +"%Y-%m-%d")  
# 字符串组合生成文件名
dumpfile=poetize_db-$Now
# 检查日志文件是否存在
if [ ! -f "$logfile" ]; then
	    echo "Log file does not exist, creating..."
	        # 创建文件所在的目录
		    mkdir -p $(dirname "$logfile")
		        # 创建空的日志文件
			    touch "$logfile"
			        echo "Log file created."
			else
				    echo "Log file already exists."
fi
# 这个函数用来备份数据库
back_db() {
	# 将备份的时间、数据库名存入日志
	echo "------"$(date +%Y-%m-%d%t%A%t%T)" Beginning database "${dbname}" backup--------" >>${logfile}
	# 备份数据库,如果有错误信息也记入日志。默认utf8编码
	#--skip-opt (mysql服务运行时备份,请加此参数,防止表损坏,mysqldump可选参数)
	#--quick --force --routines --add-drop-database --add-drop-table  (存储过程也会一起备份,mysqldump可选参数)
	mysqldump --skip-opt -u${dbuser} -p${dbpasswd} --default-character-set=utf8 --quick --force --routines --add-drop-database --add-drop-table ${dbname} >${backuppath}${dumpfile}.sql 2>> ${logfile}
	echo "mysqldump --skip-opt -u${dbuser} -p${dbpasswd} --default-character-set=utf8 --quick --force --routines --add-drop-database --add-drop-table ${dbname} >${backuppath}${dumpfile}.sql 2>> ${logfile}"
	# 开始压缩数据文件
	echo $(date +%Y-%m-%d%t%A%t%T)" Beginning zip ${backuppath}${dumpfile}.sql" >>${logfile}
	# 将备份数据库文件库,并删除先前的SQL文件。如果有错误信息也记入日志。
	tar zcvf ${dumpfile}.tar.gz ${dumpfile}.sql && rm ${dumpfile}.sql 2>> ${logfile}
	# 将压缩后的文件名存入日志。
	echo "backup file name:"${dumpfile}".tar.gz" >>${logfile}
	echo -e "-------"$(date +%Y-%m-%d%t%A%t%T)" Ending database "${dbname}" backup-------\n" >>${logfile}
}
# 设置定时发送邮件通知函数
schedule_email() {
    # 获取当前时间和今天的9点时间
    current_time=$(date +%s)
    today_nine_am=$(date -d "today 09:00" +%s)
    
    # 如果当前时间已经过了今天9点,就发送明天的9点通知
    if [ $current_time -ge $today_nine_am ]; then
        target_time=$(date -d "tomorrow 09:00" +%s)
        echo "$(date +'%Y-%m-%d %H:%M:%S') - 今天9点已过,将在明天9点发送通知" >> ${logfile}
    else
        target_time=$today_nine_am
        echo "$(date +'%Y-%m-%d %H:%M:%S') - 将在今天9点发送通知" >> ${logfile}
    fi
    
    # 计算需要sleep的秒数
    sleep_seconds=$((target_time - current_time))
    
    echo "$(date +'%Y-%m-%d %H:%M:%S') - 将在 $sleep_seconds 秒后(即 $(date -d "+$sleep_seconds seconds") 发送邮件通知" >> ${logfile}
    
    # 使用nohup在后台运行
    nohup bash -c "sleep $sleep_seconds && $email_script" >> ${logfile} 2>&1 &
}

# 这个函数用来删除90天前的数据,注意,这个脚本会删除当前目录下所有的早于七天前的文件
rm_oldfile() {
	# 查找出当前目录下90天前生成的文件,并将之删除
	find /home/dbback/sqlzip/ -type f -mtime +30 -exec rm {} \;
}
# 切换到数据库备份的目录。如果不做这个操作,压缩文件时有可能会错误
cd ${backuppath}
# 运行备份数据函数
back_db
# 运行删除文件函数
rm_oldfile
# 运行发送邮件函数
schedule_email
shell

2. 邮件通知脚本(send_backup_email.sh)#

#!/bin/bash

# 配置部分
##############################################
MAIL_TO="touser@example.com"          # 收件人邮箱
MAIL_FROM="fromuser@example.com"        # 发件人邮箱
MAIL_SUBJECT="数据库备份结果 - $(date +'%Y-%m-%d %H:%M')"

# SMTP配置
SMTP_SERVER="smtp.example.com"
SMTP_PORT="465"
SMTP_USER="user@example.com"
SMTP_PASSWORD="********"

# 路径配置
BACKUP_DIR="/home/dbback/sqlzip/"
LOG_FILE="/home/dbback/log/poetize_db_backup.log"
##############################################

# 获取最新备份文件
LATEST_BACKUP=$(ls -t ${BACKUP_DIR}*.tar.gz 2>/dev/null | head -n 1)

# 检查备份状态并构建消息
if [ -z "$LATEST_BACKUP" ]; then
    STATUS_LINE="数据库备份状态【异常】"
    DETAIL_LINE="错误详情:未找到任何备份文件!"
    ATTACHMENT="$LOG_FILE"
else
    BACKUP_TIME=$(stat -c %Y "$LATEST_BACKUP")
    CURRENT_TIME=$(date +%s)
    TIME_DIFF=$(( (CURRENT_TIME - BACKUP_TIME) / 86400 ))
    
    if [ $TIME_DIFF -gt 1 ]; then
        STATUS_LINE="数据库备份状态【异常】"
        DETAIL_LINE="错误详情:最新备份已超过1天(${TIME_DIFF}天前)"
        ATTACHMENT="$LOG_FILE"
    else
        STATUS_LINE="数据库备份状态【成功】"
        DETAIL_LINE="最新备份文件:$(basename "$LATEST_BACKUP")"
        ATTACHMENT="$LATEST_BACKUP"
    fi
fi

# 构建邮件内容
MAIL_CONTENT=$(cat <<EOF
${STATUS_LINE}

${DETAIL_LINE}

=== 备份时间 ===
$(date -d @${BACKUP_TIME} +'%Y-%m-%d %H:%M:%S')
EOF
)

# 发送邮件
echo "$MAIL_CONTENT" | mailx -v \
-s "$MAIL_SUBJECT" \
-a ${ATTACHMENT} \
-S smtp="smtps://${SMTP_SERVER}:${SMTP_PORT}" \
-S smtp-auth=login \
-S smtp-auth-user="${SMTP_USER}" \
-S smtp-auth-password="${SMTP_PASSWORD}" \
-S from="${MAIL_FROM}" \
${MAIL_TO}

# 记录发送结果
if [ $? -eq 0 ]; then
    echo "$(date +'%Y-%m-%d %H:%M:%S') - 备份通知邮件已发送至 $MAIL_TO" >> "$LOG_FILE"
else
    echo "$(date +'%Y-%m-%d %H:%M:%S') - 错误: 无法发送备份通知邮件" >> "$LOG_FILE"
fi
shell

效果如下

冷备邮件通知

四、方案特点#

  1. 自动化程度高:一键完成备份+清理+通知全流程
  2. 通知时间智能:自动选择合理时间发送邮件
  3. 状态判断准确:通过文件检查和时效验证双重确认
  4. 安全可靠:从存储到传输的全链路安全设计

冷备份的优势:

  • 提高数据安全性:就其本质而言,冷备份速度很快,因为它们仅用于复制文件和脱机工作或在关机模式下工作。这使得用户在备份过程中无法访问数据库。这种不可访问性因此成为提高数据安全性的杠杆,自动消除了意外覆盖导致数据变异或彻底删除的可能性。
  • 降低数据损坏的可能性:热备份随时可能发生电涌和电力中断。这些可能性使数据和文件容易受到损坏、删除和突变的影响。然而,冷备份大大减少了这些数据损坏的可能性,因为它们被设计为不受可能发生的电涌、电力中断以及病毒和黑客攻击的影响。
  • 保证数据的一致性:冷备份时用户会被注销,无法访问数据库。这可确保备份的数据和文件未被更改并保留其原始信息。通过这样做,冷备份保证了数据的一致性。
  • 易于恢复:只需将文件复制回来即可轻松恢复到某个时间点。
  • 低成本:以低维护成本确保高数据库安全性。
MySQL数据冷备+邮件推送提醒
https://shujichen.com/blog/datacoldbackupemailpush
Author Jichen
Published at April 11, 2025
Comment seems to stuck. Try to refresh?✨