MySQL数据库定期备份脚本,mysqldump+压缩+过期

MySQL数据库定期备份脚本是线上站点和数据安全的基础保障。
这篇文章会带你用 mysqldump 导出数据库,用 gzip 压缩备份文件,再配合 crontab 定时执行,并让脚本自动删除超过保留天数的旧备份。
按本文操作,你最终能得到一套每天自动运行、占用空间可控、且能手动验证恢复的备份方案。

动手前先确认三件事

在写脚本之前,先确认服务器上已经具备下面的条件,避免执行到一半才发现缺东西。

  • MySQL 客户端已安装:因为 mysqldump 包含在客户端工具中,执行 mysql --version 能看到版本号就说明已安装。如果提示 command not found,需要先安装 mysql-client 或对应数据库客户端组件。
  • 备份账号有权限:建议单独创建一个备份账号,只授予 SELECTLOCK TABLESSHOW VIEWEVENTTRIGGER 等备份所需权限,不要直接用 root 跑定时任务。
  • 磁盘空间足够:备份目录至少预留数据库体积 2 倍以上的空间,压缩后一般会更小,但为了安全请留足余量。

确认以上三点后,就可以开始写脚本了。

编写备份脚本的完整代码

我习惯把脚本放在 /opt/mysql_backup/ 目录下,你也可以换成自己的路径。
先创建目录:

mkdir -p /opt/mysql_backup

然后新建脚本文件:

vim /opt/mysql_backup/backup_mysql.sh

粘贴下面的内容,注意替换数据库账号、密码和库名:

#!/bin/bash
# MySQL 定期备份脚本
# 功能:mysqldump 导出 + gzip 压缩 + 过期备份自动删除

BACKUP_DIR="/opt/mysql_backup"         # 备份文件存放目录
DB_USER="backup_user"                  # 数据库备份账号
DB_PASS="你的密码"                     # 备份账号密码
DB_NAME="db1 db2"                      # 要备份的数据库,多个库用空格分隔
RETENTION_DAYS=7                        # 备份文件保留天数

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

# 创建备份目录(如果不存在)
mkdir -p "$BACKUP_DIR"

# 使用 mysqldump 导出,并用 gzip 压缩
mysqldump -u"$DB_USER" -p"$DB_PASS" \
    --databases $DB_NAME \
    --single-transaction \
    --routines --triggers \
    --default-character-set=utf8mb4 \
    | gzip > "$BACKUP_DIR/mysql_${DATE}.sql.gz"

# 删除超过保留天数的备份文件
find "$BACKUP_DIR" -type f -name "mysql_*.sql.gz" -mtime +"$RETENTION_DAYS" -exec rm -f {} \;

echo "备份完成:$BACKUP_DIR/mysql_${DATE}.sql.gz"

这里有几个关键参数说明一下:

  • --single-transaction:对 InnoDB 表实现一致性备份,备份过程中不锁表,适合生产库。
  • --routines --triggers:导出存储过程、函数和触发器,防止恢复后缺少这些对象。
  • --default-character-set=utf8mb4:避免中文乱码。
  • find ... -mtime +7:删除 7 天前的文件,这里的数字对应 RETENTION_DAYS

保存后给脚本加执行权限:

chmod +x /opt/mysql_backup/backup_mysql.sh

直接手动跑一次,确认没有报错:

/opt/mysql_backup/backup_mysql.sh

如果备份成功,/opt/mysql_backup/ 目录下会出现一个 mysql_20250101_120000.sql.gz 类似的文件。

用 crontab 挂上每天定时执行

手动跑通后,下面设置定时任务。
执行 crontab -e 打开当前用户的 cron 表,追加一行:

0 3 * * * /bin/bash /opt/mysql_backup/backup_mysql.sh >> /opt/mysql_backup/backup.log 2>&1

这行的意思是每天凌晨 3 点执行一次备份脚本,并把输出写入日志。
保存后,确认 cron 服务正在运行:

systemctl status cron

如果系统是 CentOS,服务名可能是 crond,用 service crond status 查看。
看到 active (running) 就说明定时任务在正常排队。

常见报错和避坑指南

第一次写脚本最容易遇到下面几个问题,提前了解能省不少时间。

mysqldump: command not found

说明 MySQL 客户端不在 PATH 里。
可以先用 which mysqldump 找到完整路径,比如 /usr/local/mysql/bin/mysqldump,然后把脚本里的 mysqldump 替换成完整路径。

ERROR 1045 (28000): Access denied for user

备份账号权限不足或密码错误。
建议用下面语句创建专用账号:

CREATE USER 'backup_user'@'localhost' IDENTIFIED BY '密码';
GRANT SELECT, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER ON *.* TO 'backup_user'@'localhost';
FLUSH PRIVILEGES;

备份文件是 0 字节

通常是账号权限不足导致导出失败,但脚本没有捕获错误。
建议在脚本开头加上 set -e,让任意命令执行失败时直接退出,避免生成无效空文件。

密码明文写在脚本里有风险

如果担心安全问题,可以把账号密码写入 /root/.my.cnf,然后脚本里不再传 -p 参数。
这样只有 root 能读取该文件,相对更安全。

find 的 -mtime 计算逻辑

-mtime +7 表示超过 7 天前的文件,不是删除最近 7 个文件。
如果你想按文件数量保留,可以用 ls -t | tail -n +n 的方式,但按天数是更常见的运维习惯。

最后验证一下备份是否真的可用

备份脚本跑通不代表万事大吉,如果恢复不了,备份就等于零。
建议每次调整脚本后,都做一次恢复测试。
下面是一条快速验证命令,把备份导入到一个新库:

gunzip -c /opt/mysql_backup/mysql_20250101_120000.sql.gz | mysql -uroot -p -e "CREATE DATABASE IF NOT EXISTS test_restore;" && \
gunzip -c /opt/mysql_backup/mysql_20250101_120000.sql.gz | mysql -uroot -p test_restore

执行后,用 mysql -uroot -p -e "USE test_restore; SHOW TABLES;" 查看是否成功导入表结构。
检查无误后删除测试库即可。

另外,crontab 日志也是验证的重要手段。
执行 cat /opt/mysql_backup/backup.log,能看到每次任务的输出和错误信息。
如果某个时间点没有记录,优先排查 cron 服务状态和脚本路径是否写错。

按照这套流程,你的 MySQL 数据库定期备份脚本就已经完整落地了。
建议每周抽查一次备份文件大小和压缩包完整性,尤其是在表结构变动比较大的时候。
如果后续遇到备份失败,优先排查账号权限、磁盘空间和脚本路径这三项。
希望这篇教程能帮你把备份任务稳定跑起来。

分享到:
上一篇
Debian系统ufw防火墙生产配置
下一篇
Nginx 502 bad gateway高频出现
1
系统公告

机房迁移升级通知

尊敬的用户: IP 段 103.23.148.x、156.224.29.x 原香港一区线路波动、攻击频繁,平台定于 7 月 5 日凌晨分批迁移至香港 GIA 机房,硬件升级 AMD 铂金机型。 迁移均在凌晨操作,最大程度降低业务影响,迁移期间服务器临时关机; 升级后配置不降低、费用不涨价,数据默认同步迁移; 迁移后 IP 全部更换,请及时修改域名解析、防火墙白名单; 建议提前备份重要数据,有问题可联系在线客服。 感谢理解与支持! 泽御云科技 2026.06.30
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意