本文约 3,613 字,预计阅读 10 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:插件会失效,mysqldump 不会
备份插件依赖 WordPress 能正常运行——站点白屏时它们也没法用。而 mysqldump 只依赖数据库本身,是最后一道保险。
它也是最有掌控力的方式:可以只备份某几张表、可以加条件、可以压缩、可以配合 cron 完全自动化。
原理分析:mysqldump 输出的是什么
本质上是一堆 SQL 语句:
DROP TABLE IF EXISTS `wp_posts`;
CREATE TABLE `wp_posts` (...);
INSERT INTO `wp_posts` VALUES (...),(...);
恢复就是把这个文件喂给 mysql,它会重建表并插入数据。
关键概念:
- 一致性:备份过程中数据还在变,如果不加锁或使用事务,可能拿到”半新半旧”的快照;
- 锁表:默认
mysqldump会锁表(对 MyISAM 必要),对 InnoDB 可用--single-transaction避免; - 扩展性:大库导出耗时,需要考虑对线上请求的影响。
保姆级实操
第一步:最基础的备份命令
mysqldump -u wpuser -p wordpress > wp-$(date +%F).sql
第二步:生产环境推荐参数
mysqldump \
-u wpuser -p \
--single-transaction \
--quick \
--routines --triggers --events \
--default-character-set=utf8mb4 \
--hex-blob \
wordpress | gzip > wp-$(date +%F).sql.gz
参数说明:
| 参数 | 作用 |
|---|---|
--single-transaction |
InnoDB 下不加锁的一致性快照 |
--quick |
逐行读取,避免大表撑爆内存 |
--routines --triggers --events |
包含存储过程、触发器、事件 |
--default-character-set=utf8mb4 |
明确字符集,避免乱码 |
--hex-blob |
二进制字段用十六进制,避免编码问题 |
第三步:避免明文密码
不要写 -p密码(会进命令历史)。用配置文件:
# ~/.my.cnf 权限必须 600
[client]
user=wpuser
password=你的密码
chmod 600 ~/.my.cnf
mysqldump wordpress > backup.sql # 无需再输密码
第四步:只备份部分表
mysqldump wordpress wp_posts wp_postmeta wp_options > content-only.sql
这在”只想回滚文章内容、不想覆盖设置”时非常有用。
第五步:用条件导出(高级)
只导出已发布文章(不含草稿与修订版本):
mysqldump wordpress wp_posts --where="post_status='publish' AND post_type IN ('post','page')" > published.sql
第六步:排除垃圾数据减小体积
# 先清理再备份
wp post delete $(wp post list --post_type=revision --format=ids) --force 2>/dev/null
wp comment delete $(wp comment list --status=spam --format=ids) --force 2>/dev/null
wp transient delete --all
# 或者导出时跳过某些表
mysqldump wordpress \
--ignore-table=wordpress.wp_options \
> without-options.sql
第七步:自动化脚本
#!/usr/bin/env bash
# /usr/local/bin/db-backup.sh
set -euo pipefail
DB="wordpress"
BK="/backup/db"
KEEP=14
mkdir -p "$BK"
FILE="$BK/${DB}-$(date +%F-%H%M).sql.gz"
mysqldump --single-transaction --quick --routines --triggers \
--default-character-set=utf8mb4 --hex-blob "$DB" | gzip > "$FILE"
# 校验文件大小
SIZE=$(stat -c%s "$FILE")
if [ "$SIZE" -lt 1024 ]; then
echo "备份异常:文件过小 $SIZE" | mail -s "备份失败告警" admin@example.com
exit 1
fi
# 清理旧备份
find "$BK" -name "${DB}-*.sql.gz" -mtime +$KEEP -delete
echo "$(date) 备份完成 $FILE ($SIZE bytes)" >> /var/log/db-backup.log
crontab:
0 3 * * * /usr/local/bin/db-backup.sh
第八步:恢复
# 方法 A
gunzip < wp-2026-10-10.sql.gz | mysql wordpress
# 方法 B(WP-CLI)
gunzip < wp-2026-10-10.sql.gz | wp db import -
恢复前建议先确认:
head -20 wp-2026-10-10.sql # 看头部注释里的版本与字符集
第九步:校验备份有效性
# 建临时库导入
mysql -e "CREATE DATABASE wp_test_restore;"
gunzip < wp-2026-10-10.sql.gz | mysql wp_test_restore
mysql -e "SELECT COUNT(*) FROM wp_test_restore.wp_posts;"
mysql -e "DROP DATABASE wp_test_restore;"
常见踩坑与失败案例
- 备份文件是空的 —— 密码错误或库名写错,
mysqldump输出到 stdout 而错误到 stderr,脚本没检查就以为成功了。一定要校验文件大小或行数。 - 案例:某站用
mysqldump每天备份,一次迁移时导入失败,报Unknown collation。原因是源库 MySQL 8(utf8mb4_0900_ai_ci)目标库 MariaDB。解决办法是导出时加--compatible=mysql40或事后替换排序规则。 - 大表导出拖垮线上 —— 没加
--single-transaction导致锁表,前台卡死。InnoDB 必须加这个参数。 - MyISAM 表无法用 single-transaction —— 会退化为锁表。把表转成 InnoDB:
ALTER TABLE wp_posts ENGINE=InnoDB; - 忘记包含
wp_options—— 恢复后站点设置全丢。只备份部分表时要清楚自己在做什么。 - 备份和站点在同一块磁盘 —— 磁盘故障一起完蛋,务必 rsync 到异地。
总结
mysqldump 是 WordPress 数据库备份的基石,一条命令能覆盖 90% 场景。生产环境记住四个参数:--single-transaction(不锁表)、--quick(省内存)、--default-character-set=utf8mb4(防乱码)、--hex-blob(二进制安全)。再配上”文件大小校验 + 异地同步 + 定期恢复演练”,你的数据库备份才算真正可靠。脚本一定要有失败告警——静默失败的备份,比没有备份更危险。
