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

来源:这里教程网 时间:2026-02-28 20:39:53 作者:

用 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
压缩。别用
bzip2
xz
——它们压缩快但 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  遇到已存在表、重复主键就会停住。线上恢复不能人工干预,得加 <code>--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

最容易被忽略的是:脚本里所有命令(

mysqldump
mysql
date
)都要写绝对路径,cron 默认 PATH 很窄,
which mysqldump
结果才是真实路径。

相关推荐