Discuz数据库表优化,论坛大表清理归档
论坛运行两三年后,Discuz 的 pre_forum_post、pre_forum_thread 这类表很容易涨到几 GB,直接表现是发帖变慢、后台备份超时、MySQL 负载升高。
本文面向零基础站长,讲清楚如何安全地清理和归档大表,让论坛恢复轻快。
先判断哪些表需要处理
登录宝塔面板,进入「数据库」→ 点击对应 Discuz 库的「管理」,或直接用 phpMyAdmin 查看。
在 SQL 窗口执行:
SELECT table_name, table_rows, data_length, index_length,
ROUND((data_length+index_length)/1024/1024,2) AS total_mb
FROM information_schema.tables
WHERE table_schema='你的数据库名'
ORDER BY total_mb DESC LIMIT 10;
结果里 total_mb 超过 500MB 的表就值得关注。
Discuz 常见的大表有:
pre_forum_post:帖子内容,通常最大pre_forum_thread:主题列表pre_common_member:用户表,一般不会太大pre_forum_attachment:附件索引
结论:优先处理 pre_forum_post 和 pre_forum_thread,它们占了论坛 80% 以上的数据量。
清理前必须做的三件事
第一,完整备份数据库。 在宝塔「数据库」页面点击「备份」,或者用命令行:
mysqldump -u root -p 你的数据库名 > /www/backup/discuz_$(date +%Y%m%d).sql
备份文件建议下载到本地一份,不要只留在服务器上。
第二,关闭论坛发帖。 进入 Discuz 后台 →「全局」→「站点信息」→ 将「关闭论坛」设为「是」,避免清理过程中有新数据写入。
第三,确认 MySQL 版本。 在宝塔「软件商店」查看 MySQL 版本,5.7 和 8.0 的部分语法有差异,后面步骤会说明。
归档旧帖子数据的两种方式
方式一:按时间归档到新表
适合保留老帖子但不想让它拖慢主表的情况。
以 pre_forum_post 为例,先建归档表:
CREATE TABLE pre_forum_post_archive LIKE pre_forum_post;
然后把 2022 年之前的帖子搬过去(时间戳按自己论坛情况调整):
INSERT INTO pre_forum_post_archive
SELECT * FROM pre_forum_post WHERE dateline < UNIX_TIMESTAMP('2022-01-01');
确认数据搬完后删除原表旧数据:
DELETE FROM pre_forum_post WHERE dateline < UNIX_TIMESTAMP('2022-01-01');
注意:DELETE 大表会锁表,建议在凌晨低峰期操作,或者分批删除,每次 5000 行。
方式二:直接清理回收站和垃圾帖
Discuz 后台 →「内容」→「论坛帖子管理」→ 筛选「回收站」中的帖子,批量删除。
对应的表数据也会减少。
如果帖子量特别大,可以在 SQL 中直接清理:
DELETE FROM pre_forum_post WHERE invisible = -1;
DELETE FROM pre_forum_thread WHERE invisible = -1;
invisible = -1 表示回收站状态。
执行前先用 SELECT COUNT(*) 确认数量。
优化表空间,释放磁盘
删除数据后,表文件不会自动缩小,需要执行:
OPTIMIZE TABLE pre_forum_post;
OPTIMIZE TABLE pre_forum_thread;
MySQL 8.0 中如果表使用了 InnoDB 且开启了 innodb_file_per_table,这个命令会重建表并释放空间。
执行时间取决于表大小,几 GB 的表可能需要几分钟到十几分钟。
宝塔面板也可以在「数据库」→「管理」→ phpMyAdmin 中选中表,点击「优化表」。
验证方式: 再次执行前面的 information_schema 查询,对比 total_mb 是否下降。
日常维护比一次性清理更重要
清理完成后,建议做三件事防止再次膨胀:
- 在 Discuz 后台开启「帖子自动回收」:后台 →「论坛」→「论坛设置」→ 回收站设置,将保留天数设为 30 天。
- 每月执行一次
OPTIMIZE TABLE,可以写到宝塔的计划任务里。 - 如果论坛活跃度高,考虑按年份分表,比如每年一个
pre_forum_post_2024,通过 Discuz 插件或自定义代码路由查询。
判断标准:如果单表超过 2GB 且日发帖量低于 100,归档旧数据是最划算的方案;
如果日发帖量很高,分表更合适。
常见问题
清理后论坛打不开怎么办? 先恢复备份,检查是否误删了 pre_forum_thread 中仍被引用的记录。
Discuz 的帖子与主题通过 tid 关联,删除时要保证两边一致。
OPTIMIZE TABLE 报错怎么办? MySQL 5.7 某些版本对 InnoDB 的 OPTIMIZE 会提示不支持,
可以改用 ALTER TABLE pre_forum_post ENGINE=InnoDB; 重建表。
归档表还需要保留吗? 如果只是清理垃圾数据,归档表确认无误后可以删除;
如果是历史帖子,建议保留并定期备份。
操作后发帖速度没变化? 检查 MySQL 慢查询日志,可能是其他表或索引问题,不一定是数据量导致。
整个流程的核心是:先备份,再归档,后优化。
不要跳过备份直接 DELETE,也不要在高峰期执行大表操作。
按本文步骤走完,论坛数据库通常能缩小 30%-60%,备份和查询速度会有明显改善。