mysql数据库的备份与恢复的自动化脚本

10次阅读

生产环境全库备份需用mysqldump加–single-transaction、–routines、–triggers、–events、–default-character-set=utf8mb4、–hex-blob、–set-gtid-purged=OFF,并强制TCP连接、按时间戳命名+gzip压缩,且脚本中所有命令须写绝对路径。

mysql数据库的备份与恢复的自动化脚本

mysqldump 做全库备份,关键在参数组合

直接执行 mysqldump -u root -p database_name 很容易失败,不是权限问题就是锁表中断。生产环境必须加 --single-transaction(InnoDB 专用)和 --routines --triggers --events,否则存储过程、触发器会丢失。--skip-lock-tables 要慎用——它不适用于 MyISAM 表,且可能造成备份不一致。

实际脚本中建议固定使用:

  • --default-character-set=utf8mb4:避免中文乱码
  • --hex-blob:安全导出 BLOB 类型(如图片、加密字段)
  • --set-gtid-purged=OFF:关闭 GTID 记录,否则恢复时可能报错 Error 1840 (HY000)
  • 加上 -h 127.0.0.1 强制走 TCP 连接,绕过 unix socket 权限限制

按日期自动命名 + 压缩归档,防止磁盘写满

不带时间戳的备份文件会互相覆盖,而裸 SQL 文件体积大、传输慢。脚本里必须用 $(date +%Y%m%d_%H%M) 生成唯一文件名,并立刻用 gzip 压缩。别用 bzip2xz——它们压缩快但 CPU 占用高,夜间备份可能拖慢数据库响应。

示例片段(Shell):

DB_NAME="myapp" DUMP_FILE="/backup/${DB_NAME}_$(date +%Y%m%d_%H%M).sql.gz" mysqldump -h 127.0.0.1 -u backup_user -p'xxx' --single-transaction --routines --triggers --events --set-gtid-purged=OFF --default-character-set=utf8mb4 "$DB_NAME" | gzip > "$DUMP_FILE"

注意:backup_user 需提前授权:GRANT select, LOCK TABLES, SHOW VIEW, TRIGGER ON `myapp`.* TO 'backup_user'@'localhost';

用 mysql 命令恢复时,忽略错误比中断更实用

直接 mysql -u root -p database_name 遇到已存在表、重复主键就会停住。线上恢复不能人工干预,得加 --force 参数让命令跳过错误继续执行。但要注意:--force 不会跳过语法错误,所以备份前务必验证 SQL 可执行性(可用 mysql -e "source /path/to/backup.sql;" 测试)。

恢复脚本关键点:

  • 先创建空库:mysql -e "CREATE DATABASE if NOT EXISTS $DB_NAME CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
  • 再导入:zcat "$DUMP_FILE" | mysql -u root -p'xxx' --force "$DB_NAME"
  • 最后检查行数是否明显异常(比如比上次少 90%),可加一句 mysql -Nse "SELECT count(*) FROM $DB_NAME.table1" 做简单校验

crontab 定时任务要避开高峰,且必须重定向日志

每天凌晨 2 点跑备份看似合理,但如果数据库凌晨有批量导入或报表任务,IO 就会打满。建议设为 0 3 * * * (3 点)并配合 ionice -c2 -n7 降低 IO 优先级。

crontab 行必须带完整路径和日志重定向,否则失败了根本看不到报错:

0 3 * * * /usr/bin/ionice -c2 -n7 /bin/bash /opt/scripts/mysql_backup.sh >> /var/log/mysql_backup.log 2>&1

最容易被忽略的是:脚本里所有命令(mysqldumpmysqldate)都要写绝对路径,cron 默认 PATH 很窄,which mysqldump 结果才是真实路径。

text=ZqhQzanResources