首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >WordPress 数据库清理:修订版、过期临时数据、autoload 选项,哪些能安全删,删前怎么备份

WordPress 数据库清理:修订版、过期临时数据、autoload 选项,哪些能安全删,删前怎么备份

原创
作者头像
用户10345225
发布于 2026-10-26 13:43:40
发布于 2026-10-26 13:43:40
1630
举报

先把结论列出来:

  • 能直接删:文章修订版(revision)、自动草稿(auto-draft)、回收站里的内容、已经过期的 transient。
  • 能删,但要先确认是谁写的:孤立的 postmeta / commentmeta / termmeta、重复或已经不存在的定时任务。
  • 不能删数据行,只能改属性:autoload 很大的 options。整行删掉,插件或主题会直接报错。
  • 不要手动修改:siteurl、home、active_plugins、template、stylesheet、rewrite_rules 这类核心 options,以及插件自己建的表。

下面按「先量体积、再备份并验证、再逐项处理、最后验证」的顺序来。全程请在预发布环境先跑一遍。

0. 先测量体积,不要凭感觉删

代码语言:sql
复制
SELECT table_name,
       ROUND(data_length/1024/1024, 1) AS data_mb,
       ROUND(index_length/1024/1024, 1) AS index_mb,
       table_rows
FROM information_schema.tables
WHERE table_schema = DATABASE()
ORDER BY data_length + index_length DESC
LIMIT 20;

wp_posts、wp_postmeta、wp_options 一般排在最前面。先看清楚是哪张表大,再决定动哪张表;很多站体积大,原因来自插件自建表,而不是文章。

1. 备份,并且验证备份能恢复

代码语言:bash
复制
# 方式一:wp-cli
wp db export /tmp/wp-backup-$(date +%F-%H%M).sql --add-drop-table

# 方式二:mysqldump(表是 InnoDB 时用 --single-transaction 避免锁表)
mysqldump --single-transaction --quick --routines --triggers \
  --default-character-set=utf8mb4 \
  -h "$DB_HOST" -u "$DB_USER" -p "$DB_NAME" \
  | gzip > /tmp/wp-backup-$(date +%F-%H%M).sql.gz

只生成文件并不算验证。需要确认三件事:

代码语言:bash
复制
ls -lh /tmp/wp-backup-*
# 未压缩的导出文件可以直接数表
zcat /tmp/wp-backup-*.sql.gz | grep -c 'CREATE TABLE'
# 和下面这个数字对比
mysql -N -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='$DB_NAME'"

然后实际恢复一次到临时库:

代码语言:bash
复制
mysql -h "$DB_HOST" -u "$DB_USER" -p -e "CREATE DATABASE wp_restore_test"
zcat /tmp/wp-backup-*.sql.gz | mysql -h "$DB_HOST" -u "$DB_USER" -p wp_restore_test
mysql -h "$DB_HOST" -u "$DB_USER" -p -N -e "SELECT COUNT(*) FROM wp_restore_test.wp_posts"

数字对得上,再往下走。

2. 文章修订版(revision)

能删。代价是编辑器的「版本对比」历史会消失。如果站点有审计要求,或者用了依赖修订版做对比的插件,先确认再删。

代码语言:sql
复制
SELECT COUNT(*) AS revisions FROM wp_posts WHERE post_type = 'revision';

删除时要把 postmeta 一起删,否则 wp_postmeta 里会留下永远没人引用的行:

代码语言:sql
复制
DELETE p, pm
FROM wp_posts p
LEFT JOIN wp_postmeta pm ON pm.post_id = p.ID
WHERE p.post_type = 'revision';

表很大时分批跑,避免一次删太多,给 binlog 和 IO 带来太大压力:

代码语言:sql
复制
DELETE p, pm
FROM wp_posts p
LEFT JOIN wp_postmeta pm ON pm.post_id = p.ID
WHERE p.post_type = 'revision' AND p.ID < 100000;
-- 重复执行,把 100000 往上加,直到影响行数为 0

如果以后不想再产生修订版,在 wp-config.php 里加:

代码语言:php
复制
define('WP_POST_REVISIONS', 5);

3. 自动草稿和回收站

auto-draft 是编辑器打开但没保存留下的空壳,可以直接删。回收站建议先留一段时间,再按修改时间删:

代码语言:sql
复制
DELETE p, pm
FROM wp_posts p
LEFT JOIN wp_postmeta pm ON pm.post_id = p.ID
WHERE p.post_type = 'auto-draft'
  AND p.post_date < DATE_SUB(NOW(), INTERVAL 7 DAY);

DELETE p, pm
FROM wp_posts p
LEFT JOIN wp_postmeta pm ON pm.post_id = p.ID
WHERE p.post_status = 'trash'
  AND p.post_modified < DATE_SUB(NOW(), INTERVAL 30 DAY);

注意 post_status = 'trash' 不只包含文章,page、自定义文章类型都可能在里面,删之前先用同样的条件 SELECT 一遍看看内容。

4. 过期 transient

transient 是带过期时间的临时缓存,过期后不会自动消失,会一直留在 wp_options 里。删它是安全的,代价是相关缓存要重建,短时间内站点可能稍慢。

先看规模:

代码语言:sql
复制
SELECT COUNT(*) FROM wp_options WHERE option_name LIKE '\_transient\_%';

_transient_ 是 11 个字符,所以 SUBSTRING(option_name, 12) 取到的就是键名。先删过期的值行,再删对应的 timeout 行:

代码语言:sql
复制
-- 1) 删已过期的 transient 值
DELETE o FROM wp_options o
JOIN wp_options t
  ON t.option_name = CONCAT('_transient_timeout_', SUBSTRING(o.option_name, 12))
WHERE o.option_name LIKE '\_transient\_%'
  AND o.option_name NOT LIKE '\_transient\_timeout\_%'
  AND CAST(t.option_value AS UNSIGNED) < UNIX_TIMESTAMP();

-- 2) 删对应的 timeout 行
DELETE FROM wp_options
WHERE option_name LIKE '\_transient\_timeout\_%'
  AND CAST(option_value AS UNSIGNED) < UNIX_TIMESTAMP();

顺序不能反:先删 timeout 行,第一步就 join 不到记录了。

多站点要对每张 wp_*_options 分别执行,或者用 wp site list --field=url 循环。

不建议「把所有 transient 一次性删掉」:正在被使用、还没过期的缓存被清掉,会瞬间把请求全部发到数据库。

5. autoload:只能改属性,不能删数据行

WordPress 每次请求都会把 autoload 为 yes/on 的 options 一次性读进内存。这类选项太多、太大,会拖慢每一个请求。

代码语言:sql
复制
SELECT option_name, LENGTH(option_value) AS bytes, autoload
FROM wp_options
WHERE autoload IN ('yes','on')
ORDER BY bytes DESC
LIMIT 30;

看到某个插件写的选项排在最前面,正确的做法是:先找插件本身有没有清理入口,或者停用插件后由它自己删;确实要保留数据又不想自动加载,再改属性:

代码语言:sql
复制
UPDATE wp_options SET autoload = 'no' WHERE option_name = 'your_option_name';

改完刷新缓存:

代码语言:bash
复制
wp cache flush
# 多站点
wp site list --field=url | xargs -I{} wp cache flush --url={}

还有一个经常被忽略的来源:装了又不用、或者卸载了却没带走自己选项的插件。卸载插件时删不删自己的 options,由插件自己决定,WordPress 没有统一保证,所以最省事的做法是装之前就想清楚。我们(AumCreate)在 wordpress.org 上放的几个免费插件 AumLang、AumViso、AumCrawl、AumDigital 也一样会往库里写东西,用不上就别装;已经装了的,先停用,看插件本身有没有提供清理数据的入口,再决定要不要动 SQL。插件清单在这里:https://aumcreate.com/plugins?utm_source=tencent&utm_medium=content&utm_campaign=tencent-wp-db-cleanup-safe-delete

不要改这几个的 autoload:siteurl、home、blogname、active_plugins、template、stylesheet、rewrite_rules、permalink_structure、db_version、upload_path、default_role。改了轻则后台路径错乱,重则站点打不开。

还要注意:autoload 字段在不同版本里可能是 yes/no,也可能是 on/off/auto,改之前先 SELECT DISTINCT autoload FROM wp_options 看一眼实际值。

6. 孤立的 meta

父记录已经被删掉、meta 还留着,这是插件或手动删数据留下的。删之前一定先备份,因为有些插件是故意保留这些数据的。

代码语言:sql
复制
-- 先看数量
SELECT COUNT(*) FROM wp_postmeta pm
LEFT JOIN wp_posts p ON p.ID = pm.post_id
WHERE p.ID IS NULL;

-- 确认后再删
DELETE pm FROM wp_postmeta pm
LEFT JOIN wp_posts p ON p.ID = pm.post_id
WHERE p.ID IS NULL;

DELETE cm FROM wp_commentmeta cm
LEFT JOIN wp_comments c ON c.comment_ID = cm.comment_id
WHERE c.comment_ID IS NULL;

DELETE tm FROM wp_termmeta tm
LEFT JOIN wp_terms t ON t.term_id = tm.term_id
WHERE t.term_id IS NULL;

7. 收尾:优化表、验证、观察

删完大量行之后,表文件不会自动变小,可以做一次表优化。InnoDB 的 OPTIMIZE TABLE 会重建表,需要大约等于表大小的额外磁盘空间,并且占用 IO,请放在低峰期:

代码语言:sql
复制
OPTIMIZE TABLE wp_posts, wp_postmeta, wp_options, wp_comments, wp_commentmeta;

然后按顺序验证:

代码语言:bash
复制
wp db check
wp option get siteurl
wp plugin list --status=active
curl -I https://example.com/
curl -I https://example.com/wp-admin/

前台、后台、登录页、一个带表单的页面各点一遍。观察 24 小时的错误日志和响应时间,再决定要不要继续清理下一项。

8. 这些事不要做

  • 不要 DROP TABLE,包括看起来「没用」的表。
  • 不要在 wp_options 里删不认识的 option_name,先搜代码看是谁在用。
  • 不要在生产库上执行没有 WHERE 的 DELETE。
  • 不要相信「一键优化」把所有缓存清空,正在使用的缓存也会被清掉。
  • 不要在业务高峰做 OPTIMIZE TABLE。
  • 不要把插件自建表当 WordPress 核心表处理,那是插件的数据,只能由插件自己清理。

清理是减法,判断标准是「删了之后站点行为不变,只是体积变小」。任何会影响前台表现的删除,都值得先在预发布环境跑一遍。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 0. 先测量体积,不要凭感觉删
  • 1. 备份,并且验证备份能恢复
  • 2. 文章修订版(revision)
  • 3. 自动草稿和回收站
  • 4. 过期 transient
  • 5. autoload:只能改属性,不能删数据行
  • 6. 孤立的 meta
  • 7. 收尾:优化表、验证、观察
  • 8. 这些事不要做
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档