公告:年创信息 —— 内容持续更新,欢迎指正。

数据库定期备份脚本编写

2026年10月20日 技术支持 0 阅读 2702 字
数据库定期备份脚本编写

为什么备份脚本比备份本身更重要

很多站点把备份当成一次性的任务:装好数据库,手动导出一份数据,放在服务器某个目录里,就觉得高枕无忧了。直到某天硬盘故障、误删表、或者被入侵后数据被加密,才想起那份备份——结果发现是三个月前的,恢复出来的东西几乎没法用。

定期备份的意义在于“最近可恢复点”。而脚本的作用,就是把这个恢复点尽量往前推,并且不需要你每次都记得去执行。

先想清楚要备份什么

写脚本之前,先明确几件事:

  • 01
    数据库类型

    MySQL、PostgreSQL、SQLite 的备份方式完全不同。

  • 02
    备份粒度

    全量备份最简单,但数据量大时耗时长、占空间;增量备份节省资源,但恢复时依赖完整链,出问题更隐

  • 03
    保留策略

    保留最近7天每日备份、最近4周每周备份、最近6个月每月备份,是比较常见的做法。保留太久会占满

  • 04
    存储位置

    最好和数据库所在服务器分离。同一台机器上,硬盘挂了备份也跟着挂。异地、对象存储、另一台内网机

一个可用的 MySQL 备份脚本示例

以下脚本适合中小型站点,逻辑清晰,也容易改成其他数据库。

“`bash

#!/bin/bash

# 基础配置

DB_USER="backup_user"

DB_PASS="YourStrongPassword"

DB_NAME="your_db"

BACKUP_DIR="/data/backups/mysql"

DATE=$(date +%F)

RETENTION_DAYS=7

# 创建当日目录

mkdir -p "$BACKUP_DIR/$DATE"

# 执行全量备份,同时压缩

mysqldump -u"$DB_USER" -p"$DB_PASS" –single-transaction –routines –triggers "$DB_NAME" | gzip > "$BACKUP_DIR/$DATE/$DB_NAME.sql.gz"

# 检查备份是否成功

if [ $? -eq 0 ]; then

echo "$(date '+%Y-%m-%d %H:%M:%S') 备份成功:$DB_NAME.sql.gz"

else

echo "$(date '+%Y-%m-%d %H:%M:%S') 备份失败,请检查错误日志"

# 可以在这里追加发送告警邮件的命令

exit 1

fi

# 清理7天前的备份

find "$BACKUP_DIR" -type d -name "20*" -mtime +$RETENTION_DAYS -exec rm -rf {} ;

“`

几个细节值得说明:

  • `–single-transaction` 对 InnoDB 表有效,备份过程中不影响业务读写,避免锁表。
  • `–routines` 和 `–triggers` 把存储过程、触发器也带上,否则恢复后可能缺东西。
  • `find` 是按目录的修改时间清理的,确保只删掉过期的整份备份。

如果你用的是 PostgreSQL,把 `mysqldump` 换成 `pg_dump`,再加上 `pg_restore` 验证即可。SQLite 更简单,直接复制数据库文件,但要注意在复制前执行 `VACUUM` 或使用备份 API,避免文件不一致。

让脚本真正跑起来

写好的脚本不会自动执行,需要配合系统定时任务。

把脚本放到 `/usr/local/bin/db_backup.sh` 并加上执行权限:

“`bash

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

“`

然后编辑 crontab:

“`bash

crontab -e

“`

加入:

“`cron

20 2 * * * /usr/local/bin/db_backup.sh >> /var/log/db_backup.log 2>&1

“`

表示每天凌晨 2:20 执行一次。选择凌晨是因为业务低峰,备份对数据库性能的影响最小。日志输出到独立文件里,方便事后排查。

这里有个容易踩的坑:`mysqldump` 和 `find` 等命令的路径,在 cron 环境下可能与登录 shell 不同。脚本第一行最好加上绝对路径,或者手动指定环境变量。在实战中,很多“备份没执行成功”的根源,不是脚本写错了,而是 cron 里 PATH 不对。

备份之后,还得验证

备份脚本能跑,不代表备份就有用。常见的失败原因包括:

  • 磁盘空间不足,gzip 写了一半,生成一个损坏的文件。
  • 密码变更后,脚本里的旧密码失效。
  • 数据库版本升级,老版本的 `mysqldump` 不兼容新版本的数据字典。

所以务必在脚本中检查上一步的返回值,并且至少每周手动做一次恢复测试。恢复测试不用真的覆盖生产库,可以在本地起一个新实例,导入备份文件,跑几条 count 查询,确认表数量和行数合理就行。

有条件的话,给备份文件做一次校验和记录。例如:

“`bash

md5sum "$BACKUP_DIR/$DATE/$DB_NAME.sql.gz" >> "$BACKUP_DIR/$DATE/checksum.txt"

“`

将来需要恢复时,先核对 md5,就能判断文件是否完整。

打开告警通道

备份是运维里最不适合“闷头干活”的事。脚本执行失败,最好第一时间通过邮件、短信或企业微信通知到人。简单做法是在脚本的错误分支里调 curl 请求告警接口,或者用系统自带的 `mail` 命令。具体用什么渠道不重要,重要的是“失败一定能被发现”。

如果公司已有监控系统,也可以让备份脚本输出 Prometheus 格式的指标,比如备份耗时、备份文件大小、是否成功,再配一个告警规则。这样比每天翻日志要可靠得多。

数据库备份脚本的编写,本质上不是技术难题,而是习惯问题。把备份周期定好,脚本写清楚,告警接上,再定期做一次恢复演练,数据安全就算有了基本保障。等到哪天真出了事,你会感谢那个把脚本写在凌晨两点二十的自己。

秦皇岛星岩防水保温工程有限公司 冀ICP备2026044242号-3