MySQL定时备份脚本,自动删除旧备份

前言

数据库数据很重要,必须每天自动备份。写个备份脚本,自动备份+自动删旧的,不用手动管。

一、备份脚本

完整脚本 backup_mysql.sh

#!/bin/bash

# MySQL配置
DB_USER="root"
DB_PASS="your_password"
DB_NAME="mydb"

# 备份目录
BACKUP_DIR="/data/backup/mysql"

# 保留天数
KEEP_DAYS=7

# 日期
DATE=$(date +%Y%m%d_%H%M%S)

# 备份文件名
BACKUP_FILE="$BACKUP_DIR/${DB_NAME}_${DATE}.sql.gz"

# 创建目录
mkdir -p $BACKUP_DIR

# 备份并压缩
mysqldump -u$DB_USER -p$DB_PASS $DB_NAME | gzip > $BACKUP_FILE

# 检查备份是否成功
if [ $? -eq 0 ]; then
    echo "[$(date)] 备份成功: $BACKUP_FILE"
else
    echo "[$(date)] 备份失败!"
    exit 1
fi

# 删除7天前的旧备份
find $BACKUP_DIR -name "*.sql.gz" -mtime +$KEEP_DAYS -delete

echo "[$(date)] 旧备份清理完成"

二、脚本说明

各部分解释

部分 说明
DB_USER 数据库用户名
DB_PASS 数据库密码
DB_NAME 要备份的数据库名
BACKUP_DIR 备份存放目录
KEEP_DAYS 保留几天的备份
mysqldump 备份命令
gzip 压缩,节省空间
find -mtime +7 找7天前的文件删除

备份全部数据库

mysqldump -u$DB_USER -p$DB_PASS --all-databases | gzip > $BACKUP_FILE

备份多个数据库

mysqldump -u$DB_USER -p$DB_PASS --databases db1 db2 db3 | gzip > $BACKUP_FILE

三、设置执行权限

chmod +x /data/backup/backup_mysql.sh

四、测试脚本

/data/backup/backup_mysql.sh

看有没有备份文件生成:

ls -lh /data/backup/mysql/

五、设置定时任务

每天凌晨3点备份

crontab -e

添加:

0 3 * * * /data/backup/backup_mysql.sh >> /data/backup/backup.log 2>&1

说明:

  • 0 3 * * * 每天凌晨3点
  • >> backup.log 输出写到日志
  • 2>&1 错误也写进去

查看定时任务

crontab -l

六、备份文件恢复

恢复步骤

# 解压
gunzip < mydb_20261008_030000.sql.gz | mysql -u root -p mydb

或者先解压再恢复

# 解压
gunzip mydb_20261008_030000.sql.gz

# 恢复
mysql -u root -p mydb < mydb_20261008_030000.sql

七、更完善的脚本

带日志和邮件通知的版本

#!/bin/bash

DB_USER="root"
DB_PASS="your_password"
DB_NAME="mydb"
BACKUP_DIR="/data/backup/mysql"
KEEP_DAYS=7
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/${DB_NAME}_${DATE}.sql.gz"
LOG_FILE="$BACKUP_DIR/backup.log"

mkdir -p $BACKUP_DIR

echo "========== $(date) 开始备份 ==========" >> $LOG_FILE

# 备份
mysqldump -u$DB_USER -p$DB_PASS $DB_NAME 2>>$LOG_FILE | gzip > $BACKUP_FILE

if [ $? -eq 0 ]; then
    FILE_SIZE=$(ls -lh $BACKUP_FILE | awk '{print $5}')
    echo "[$(date)] 备份成功,文件大小: $FILE_SIZE" >> $LOG_FILE
else
    echo "[$(date)] 备份失败!" >> $LOG_FILE
    # 这里可以加邮件通知
    exit 1
fi

# 删除旧备份
find $BACKUP_DIR -name "*.sql.gz" -mtime +$KEEP_DAYS -delete
echo "[$(date)] 清理 $KEEP_DAYS 天前的旧备份完成" >> $LOG_FILE

echo "========== $(date) 备份结束 ==========" >> $LOG_FILE

常见坑

坑1:密码写在脚本里不安全

脚本里明文写了数据库密码。

解决: 用mysql配置文件:

# /root/.my.cnf
[client]
user=root
password=your_password

然后脚本里就不用写密码了:

mysqldump $DB_NAME | gzip > $BACKUP_FILE

设置权限:

chmod 600 /root/.my.cnf

坑2:备份文件太大

不压缩的话备份文件很大。

解决: 用gzip压缩,能压缩到原来的1/10。

坑3:定时任务不执行

cron里写了脚本,但没执行。

原因:

  1. 脚本没加执行权限
  2. 路径写错了
  3. 环境变量不对

解决: 脚本里用全路径,比如 /usr/bin/mysqldump。

坑4:备份完没验证

备份文件损坏了都不知道。

解决: 定期找个测试库恢复一下,看备份能不能用。

坑5:备份文件存在同一台服务器

服务器挂了,备份也没了。

解决: 把备份传到远程服务器或OSS。

# 传到远程服务器
scp $BACKUP_FILE root@192.168.1.20:/data/backup/

总结

备份三步走:

  1. 写备份脚本(mysqldump + gzip + find删旧)
  2. 加执行权限
  3. 加crontab定时任务

记住: 备份不是备份了就完了,要定期验证能不能恢复!

遇到问题加QQ23979811 协助处理


emer 发布于  2026-10-8 07:59 

MySQL备份数据库,mysqldump定时备份

前言

数据库不备份,出事就完蛋。本文讲用mysqldump备份MySQL,再配crontab定时自动备份。

一、mysqldump基本用法

备份单个数据库

mysqldump -u root -p mydb > /backup/mydb.sql

输入密码后,就把mydb库备份到mydb.sql了。

备份多个数据库

mysqldump -u root -p --databases db1 db2 > /backup/mydbs.sql

备份所有数据库

mysqldump -u root -p --all-databases > /backup/all.sql

备份单个表

mysqldump -u root -p mydb users > /backup/users.sql

二、常用参数

参数 说明
--single-transaction InnoDB一致性备份,不锁表
--routines 备份存储过程和函数
--triggers 备份触发器
--events 备份事件调度器
--master-data=2 记录binlog位置,用于主从
--default-character-set=utf8mb4 指定字符集

推荐完整命令

mysqldump -u root -p \
  --single-transaction \
  --routines \
  --triggers \
  --events \
  --default-character-set=utf8mb4 \
  mydb > /backup/mydb_$(date +%Y%m%d).sql

三、压缩备份

备份完太大,直接压缩:

mysqldump -u root -p mydb | gzip > /backup/mydb.sql.gz

恢复的时候:

gunzip < /backup/mydb.sql.gz | mysql -u root -p mydb

四、定时备份脚本

创建备份脚本:

vi /usr/local/bin/mysql_backup.sh

内容:

#!/bin/bash

# 备份目录
BACKUP_DIR=/backup/mysql

# 数据库配置
DB_USER=root
DB_PASS=你的密码
DB_NAME=mydb

# 创建备份目录
mkdir -p $BACKUP_DIR

# 备份文件名(带日期)
DATE=$(date +%Y%m%d_%H%M%S)
FILE=$BACKUP_DIR/${DB_NAME}_${DATE}.sql.gz

# 执行备份
mysqldump -u$DB_USER -p$DB_PASS \
  --single-transaction \
  --routines \
  --triggers \
  --default-character-set=utf8mb4 \
  $DB_NAME | gzip > $FILE

# 删除7天前的备份
find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete

echo "备份完成:$FILE"

加执行权限:

chmod +x /usr/local/bin/mysql_backup.sh

五、配置crontab定时任务

编辑crontab:

crontab -e

加上:

# 每天凌晨2点备份
0 2 * * * /usr/local/bin/mysql_backup.sh >> /var/log/mysql_backup.log 2>&1

六、恢复备份

恢复普通备份

mysql -u root -p mydb < /backup/mydb.sql

恢复压缩备份

gunzip < /backup/mydb.sql.gz | mysql -u root -p mydb

常见坑

坑1:密码写在命令行里不安全

mysqldump -u root -p123456 mydb > xxx.sql

这样密码会出现在进程列表里。

安全做法: 用配置文件存密码。

# /root/.my.cnf
[mysqldump]
user=root
password=你的密码

权限设600:

chmod 600 /root/.my.cnf

以后备份就不用输密码了:

mysqldump mydb > xxx.sql

坑2:备份时锁表

大库备份的时候,业务卡住了。

原因: 没加 --single-transaction。

解决: InnoDB库一定要加这个参数。

坑3:备份文件是空的

备份完一看,文件0字节。

原因: 密码错了,或者数据库名错了。

解决: 先手动执行一次,看报错。

坑4:备份没包含存储过程

备份后恢复,发现存储过程没了。

原因: mysqldump默认不备份存储过程。

解决: 加 --routines 参数。

总结

三步搞定自动备份:

  1. 写备份脚本
  2. 配crontab定时执行
  3. 定期清理旧备份

记住: 备份了不算数,能恢复才算数。

遇到问题加QQ23979811 协助处理


emer 发布于  2026-10-8 07:39