# 主题：重置所有最高值耗尽所有可用的磁盘空间

**URL:** https://meta.discourse.org/t/topic-reset-all-highest-exhausts-all-available-disk-space/333837
**Category:** Bug
**Created:** [2024年十月31日 14:00 UTC](https://meta.discourse.org/t/topic-reset-all-highest-exhausts-all-available-disk-space/333837 "2024-10-31T14:00:32Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![pgcd](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pgcd/32/386957_2.png) [@pgcd](https://meta.discourse.org/u/pgcd)
#### Post date: [2024年十月31日 14:00 UTC](https://meta.discourse.org/t/topic-reset-all-highest-exhausts-all-available-disk-space/333837/1 "2024-10-31T14:00:32Z")

</div>

在我本地的一个容器中工作时，我从一个有 20 多年活动历史的 SMF2 论坛导入了数据，却遇到了 `Topic.reset_all_highest` 的一个致命 bug。  
导入数据后，我的数据库显示大约有 6 万个普通主题和大约 40 万个私信主题，而 `Topic.reset_all_highest` 中的查询会导致行数呈几何级增长，导致我的磁盘空间耗尽（最初有 120GB 可用空间）。  
我目前正尝试将查询分成可管理的小块，并直接在 Postgres 中运行它们，但这显然不是最佳方案（而且我不确定它是否有效并最终得到正确的结果）。  
我尝试查看是否有人遇到过类似问题，但一无所获，所以我怀疑这是否与我的设置有关——顺便说一句，我使用的是最新的 Docker 版本。

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2024年十月31日 15:42 UTC](https://meta.discourse.org/t/topic-reset-all-highest-exhausts-all-available-disk-space/333837/2 "2024-10-31T15:42:01Z")

</div>

我最近进行了一次中等规模的导入，但它似乎无限期地卡在了 `Topic.reset_all_highest` 上，我不得不终止 Postgres 中的查询才能继续。我以前没有遇到过这个问题，以为可能是我的 postgres 服务器过载了（它连接了很多站点）。

我的下一步是迁移到另一个 postgres 服务器，但我还没有着手去做。

---

<div class="post-metadata">

### Author: ![pgcd](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pgcd/32/386957_2.png) [@pgcd](https://meta.discourse.org/u/pgcd)
#### Post date: [2024年十月31日 16:44 UTC](https://meta.discourse.org/t/topic-reset-all-highest-exhausts-all-available-disk-space/333837/3 "2024-10-31T16:44:59Z")

</div>

在我“拆分查询”实验的前两个部分（公共主题的 X 和 Y）顺利进行后，我尝试了 Z，结果它冻结了——也就是说，根据 postgres 活动，查询是活动的，并且 `top` 显示进程正在 100% 运行。  
所以我又看了一下 SQL，找到了问题：两个查询都以这种方式结束

```plaintext
      WHERE
        topics.archetype <> 'private_message' AND
        X.topic_id = topics.id AND
        Y.topic_id = topics.id AND
          (
          topics.highest_staff_post_number <> X.highest_post_number OR
          topics.highest_post_number <> Y.highest_post_number OR
          topics.last_posted_at <> Y.last_posted_at OR
          topics.posts_count <> Y.posts_count OR
          topics.word_count <> Z.word_count
        )

```

（另一个当然是 ‘private\_message’ 作为 archetype）  
这意味着查询缺少  
`Z.topic_id = topics.id` - 这导致了整个几何级数的增加。

将查询的 WHERE 子句更改为

```plaintext
      WHERE
        topics.archetype <> 'private_message' AND
        X.topic_id = topics.id AND
        Y.topic_id = topics.id AND
        Z.topic_id = topics.id AND
          (
          topics.highest_staff_post_number <> X.highest_post_number OR
          topics.highest_post_number <> Y.highest_post_number OR
          topics.last_posted_at <> Y.last_posted_at OR
          topics.posts_count <> Y.posts_count OR
          topics.word_count <> Z.word_count
        )

```

为我解决了问题。  
我应该打开一个 PR 吗？

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2024年十月31日 18:14 UTC](https://meta.discourse.org/t/topic-reset-all-highest-exhausts-all-available-disk-space/333837/4 "2024-10-31T18:14:13Z")

</div>

> [@pgcd](#):
>
> 我应该开一个PR吗？

我认为应该。如果你能找到导致此问题的提交，那将更有说服力。

---

<div class="post-metadata">

### Author: ![pgcd](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pgcd/32/386957_2.png) [@pgcd](https://meta.discourse.org/u/pgcd)
#### Post date: [2024年十一月1日 06:00 UTC](https://meta.discourse.org/t/topic-reset-all-highest-exhausts-all-available-disk-space/333837/5 "2024-11-01T06:00:22Z")

</div>

我已经为此提交了一个 PR，但有一些不幸的限制（例如，我想不到如何测试此更改）。

> <https://github.com/discourse/discourse/pull/29539>
>
> This commit fixes an undesirable geometric query resource usage introduced in b…908abe35a0121e7df69ab3bbced259b6a2b7104
> 
> I have been unable to figure out a way of testing this usefully (as I fear it would require creating several thousands of objects), but existing tests pass and a manual test with ~400k topics succeeds after the fix, while it would hang indefinitely and/or consume all disk space before the fix.
> 
> I have reported the initial problem and my findings in https://meta.discourse.org/t/topic-reset-all-highest-exhausts-all-available-disk-space/333837

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [2024年十一月3日 21:59 UTC](https://meta.discourse.org/t/topic-reset-all-highest-exhausts-all-available-disk-space/333837/6 "2024-11-03T21:59:34Z")

</div>

此更改看起来是正确的，正在合并。

（从测试角度来看，应该有覆盖率和一个简单的测试来验证它，我们只需要确认没有回归。）
