本文约 3,884 字,预计阅读 10 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:删了一篇文章,别急着全库回滚
编辑打电话说”我把一篇写了三小时的文章删了”。这时候整库回滚会把其他同事刚发的内容一起回退,代价太大。
WordPress 其实给误删留了好几道缓冲:回收站、修订版本、自动保存。再加上备份,基本都能救回来。
原理分析:删除一篇文章到底删了什么
后台”移到回收站”实际上是把 post_status 改成 trash,数据还在表里。
后台”永久删除”或回收站自动清空(默认 30 天)才会真正 DELETE,同时删除:
wp_posts 文章记录本身
wp_postmeta 该文章的所有自定义字段(特色图片、SEO 数据等)
wp_term_relationships 与分类标签的关联
wp_comments 该文章下的评论
注意:分类和标签本身不会删(它们独立存在于 wp_terms),上传的图片文件也不会删(附件记录是独立的 post)。
所以”恢复一篇文章”= 恢复这四类记录。
保姆级实操
方法一:回收站恢复(最简单)
后台 → 文章 → 回收站 → 找到文章 → 还原。
如果后台看不到回收站(可能被代码禁用了),用 WP-CLI:
wp post list --post_status=trash --fields=ID,post_title
wp post update 123 --post_status=publish
调整回收站保留时间(wp-config.php):
define('EMPTY_TRASH_DAYS', 60); // 默认 30;设为 0 则关闭回收站
方法二:从修订版本找回
如果文章是在编辑器里被改坏(而非删除),修订版本是最快的救命稻草:
wp post list --post_type=revision --post_parent=123 --fields=ID,post_date
wp post create --from-post=456 --post_status=publish # 用某个修订版创建新文章
后台方式:编辑文章 → 右侧”修订版本”面板 → 选择某个版本 → 恢复。
限制修订版本数量:
define('WP_POST_REVISIONS', 10); // 保留 10 个;设为 false 则关闭
方法三:从备份恢复单条记录(通用)
这是本文重点,适用于”永久删除 + 有备份”的情况。
步骤 1:把备份导入成临时库
mysql -e "CREATE DATABASE wp_backup_temp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
gunzip < /backup/db/db-2026-10-09.sql.gz | mysql wp_backup_temp
步骤 2:找到那篇文章
SELECT ID, post_title, post_status, post_date
FROM wp_backup_temp.wp_posts
WHERE post_title LIKE '%关键词%' AND post_type='post';
记下 ID,比如 456。
步骤 3:导出单条记录(关键参数 --no-create-info)
mysqldump --no-create-info --skip-add-drop-table --complete-insert \
wp_backup_temp wp_posts --where="ID=456" > post-456.sql
--complete-insert 会写出完整列名,导入时更安全。
步骤 4:检查目标 ID 是否冲突
SELECT ID FROM wp_posts WHERE ID=456;
- 若无返回:直接导入,ID 保留;
- 若已存在:要么换个 ID(手工改 SQL 里的 ID,并同步改 postmeta 的 post_id),要么用
INSERT IGNORE后让 WordPress 重新分配。
步骤 5:导出并导入 postmeta
mysqldump --no-create-info --skip-add-drop-table --complete-insert \
wp_backup_temp wp_postmeta --where="post_id=456" > postmeta-456.sql
mysql wordpress < post-456.sql
mysql wordpress < postmeta-456.sql
步骤 6:同步分类关联
mysqldump --no-create-info --skip-add-drop-table --complete-insert \
wp_backup_temp wp_term_relationships --where="object_id=456" > rel-456.sql
mysql wordpress < rel-456.sql
然后更新分类计数:
wp term recount category
wp term recount post_tag
步骤 7:处理特色图片
特色图片存在 postmeta 的 _thumbnail_id,指向一个 attachment post。如果这个附件在当前站也不存在,需要一并恢复:
SELECT meta_value FROM wp_postmeta WHERE post_id=456 AND meta_key='_thumbnail_id';
假设得到 789,则:
mysqldump --no-create-info --skip-add-drop-table --complete-insert \
wp_backup_temp wp_posts --where="ID=789" > attach-789.sql
mysqldump --no-create-info --skip-add-drop-table --complete-insert \
wp_backup_temp wp_postmeta --where="post_id=789" > attachmeta-789.sql
mysql wordpress < attach-789.sql
mysql wordpress < attachmeta-789.sql
并且要把物理图片文件从备份的 uploads 里拷回来:
# 查文件路径
mysql -N -e "SELECT meta_value FROM wp_postmeta WHERE post_id=789 AND meta_key='_wp_attached_file';"
# 拷贝
cp -a /backup/files/wp-content/uploads/2026/10/xxx.jpg /var/www/site/wp-content/uploads/2026/10/
步骤 8:收尾
wp rewrite flush
wp cache flush
wp post list --post_status=publish --fields=ID,post_title | grep 关键词
没有备份时的补救
- 检查是否有修订版本(方法二);
- 检查搜索引擎缓存(百度快照、Google 缓存)能拿到正文;
- 检查 Wayback Machine(web.archive.org);
- 检查 RSS 阅读器、邮件订阅里是否保留了内容;
- 检查 CDN 缓存是否还有页面快照。
常见踩坑与失败案例
- 只恢复了 wp_posts —— 文章回来了但特色图片、SEO 设置全丢。posts + postmeta 必须成对。
- 案例:某站恢复文章后前台 404,原因是没做
wp rewrite flush;修完 404 后又发现分类计数不对(显示 0 篇),补了wp term recount才正常。 mysqldump忘了--no-create-info—— 目标表被 DROP 重建,全站文章只剩恢复的这一篇。极度危险。- ID 冲突导致恢复失败 —— 用
INSERT IGNORE会静默跳过,文章”看起来没恢复”。要先检查冲突再决定策略。 - 附件记录恢复了但文件没拷 —— 后台媒体库显示图片但前台裂图。两者都要处理。
总结
误删单篇文章的恢复优先级是:回收站 → 修订版本 → 备份单条导出。备份恢复时必须记住三点:用 --no-create-info 避免覆盖表、wp_posts 与 wp_postmeta 成对恢复、别忘了分类关联与特色图片附件。恢复完执行 wp rewrite flush 和 wp term recount。最后给一条预防建议:把 EMPTY_TRASH_DAYS 调大到 60 天、WP_POST_REVISIONS 保留 10 个,成本极低,但能挡掉绝大多数误删事故。
