移行中に70Mのカレンダーイベントが原因でディスク容量不足によりリストアが失敗する

標準のインストールでデータベースのリストアを試みていますが、マイグレーションで失敗しています。


ALTER TABLE
データベースを移行中...
例外: rake db:migrate
データベースの移行に失敗しました。
rake aborted!
StandardError: エラーが発生しました。これ以降のマイグレーションはすべてキャンセルされます: (StandardError)

PG::DiskFull: ERROR:  ファイル "base/pgsql_tmp/pgsql_tmp11009.51" に書き込めませんでした: デバイスに空き領域がありません
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rack-mini-profiler-4.0.1/lib/patches/db/pg/alias_method.rb:109:in `exec'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rack-mini-profiler-4.0.1/lib/patches/db/pg/alias_method.rb:109:in `async_exec'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-8.0.4/lib/active_record/connection_adapters/postgresql/database_state
ments.rb:167:in `perform_query'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-8.0.4/lib/active_record/connection_adapters/abstract/database_stateme
nts.rb:556:in `block (2 levels) in raw_execute'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-8.0.4/lib/active_record/connection_adapters/abstract_adapter.rb:1017:in `block in with_raw_connection'

ディスクには90GBの空き容量があります。ソースディスク上のpostgresディレクトリはわずか23GBです。

23GBのデータベースが、90GBの空き容量があるにもかかわらず、データベース移行中に失敗するのはなぜでしょうか?

ソース – サーバーバージョン: 3.5.0.beta5-dev (コミット: b16fb6a60b3f1db475cbb91a51b7d4c734370083 — 2025年5月7日)

宛先サーバーバージョン: 2026.2.0-latest (コミット: b39866eb8891648a54764755e2e36eb725bd6c73 — 4日前)

23G     /var/discourse/shared/standalone/postgres_data/
-rw-r--r-- 1 discourse discourse  16G Feb 10 21:13 site-2026-02-10-174058-v20250507013646.sql
-rw-r--r-- 1 discourse discourse 2.9G Feb 10 21:11 site-2026-02-10-174058-v20250507013646.sql.gz
root@forum-data:/shared# # 削除後
root@forum-data:/shared# du -hs postgres_data/; df -h .
24G     postgres_data/
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1       154G   87G   68G  56% /shared
....
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1       154G  154G  607M 100% /shared
overlay         154G  154G  607M 100% /
91G     postgres_data/
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1       154G  154G   82M 100% /shared
overlay         154G  154G   82M 100% /
1.1G    postgres_data/
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1       154G   65G   90G  42% /shared
overlay         154G   65G   90G  42% /
1.1G    postgres_data/
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1       154G   65G   90G  42% /shared
overlay         154G   65G   90G  42% /
1.1G    postgres_data/
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1       154G   65G   90G  42% /shared
overlay         154G   65G   90G  42% /
1.1G    postgres_data/
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1       154G   65G   90G  42% /shared
overlay         154G   65G   90G  42% /
1.1G    postgres_data/

データベースのリストア後、postgres_data は 24G でした。

マイグレーション中に何らかの理由で postgres_data が 91G に急増し、ディスクがいっぱいになってリストアが失敗しました。これは上記の Discourse バージョンを使用したクリーンインストールでの出来事です。

これはバグに違いないと思われるため、カテゴリを変更します。アップグレードを試みた際にも同様の現象を確認しています。そのアップグレードの際には、新しいサーバーに移行することで解決すると思っていましたが、どうやらそれではうまくいかないようです。

次にすべきことは、この原因となっているクエリ、またはテーブルが何であるかを確認することだと思います。その方法についてはまだよくわかりません。

「いいね!」 2

これをサポートに提出します。このメッセージはファイルシステムから直接来ており、PGが容量がないと考えている場合、それはおそらく十分な容量が確保されていないためです。

24Gのデータベースがデータベース移行中に90Gに拡張する可能性について、何かヒントはありますか?

よくわかりません。状況が発生したときに、ncduか何かを実行して確認すると思います。

dudfを使って、postgres_dataのサイズが25GBから90GBに増加し、ディスクの空き容量が(ほぼ)ゼロになってから失敗するのを確認しました。

次回は、どのクエリが実行されているかを追跡する方法を見つける必要があると思います。

少なくとも2つのサイトでこれを確認しました。1つはアップグレード時、もう1つはリストア時です。どちらも開始時にはデータベースサイズよりも多くの空き容量がありました。

多数のマイグレーションはテーブル全体を書き直すため、一時的により多くのスペースを使用する可能性があり、PostgreSQLはシステムにスペースを積極的に返却しません。

そのフォーラムでは、埋め込み(embeddings)が有効になっているAIはありますか?

私もそのようなことを考えていました。。。

それはありそうな原因ですね。。。はぁ。いいえ、AIプラグインすらインストールされていません。

「いいね!」 2

もし深掘りしたいのであれば、2025年5月のコミット時点の開発環境に手動で復元し、現在のコミットに移動してマイグレーションを一つずつ実行し、それぞれ前後のスペースを出力する(もちろんスクリプトを使ってですが :stuck_out_tongue:)ということもできます。

「いいね!」 3

OK. 本番サイトでリストアしています。移行中です。

30分間実行されているクエリがこちらです。

discourse=# SELECT pid, usename, state, query, query_start
FROM pg_stat_activity
WHERE state = 'active';
 pid |  usename  | state  |                                                    query                                                     |          query_start
-----+-----------+--------+--------------------------------------------------------------------------------------------------------------+-------------------------------
 519 | postgres  | active | SELECT pid, usename, state, query, query_start                                                              +| 2026-02-14 17:58:35.473337+00
     |           |        | FROM pg_stat_activity                                                                                       +|
     |           |        | WHERE state = 'active';                                                                                      |
 308 | discourse | active | DELETE                                                                                                      +| 2026-02-14 17:26:08.12598+00
     |           |        |   FROM calendar_events ce                                                                                   +|
     |           |        | WHERE                                                                                                       +|
     |           |        |   ce.id IN (SELECT DISTINCT(ce3.id) FROM calendar_events ce2                                                +|
     |           |        |             LEFT JOIN calendar_events ce3 ON ce3.user_id = ce2.user_id AND ce3.description = ce2.description+|
     |           |        |             WHERE ce2.start_date >= (ce3.start_date - INTERVAL '1 days')                                    +|
     |           |        |               AND ce2.start_date <= (ce3.start_date + INTERVAL '1 days')                                    +|
     |           |        |               AND ce2.timezone IS NOT NULL                                                                  +|
     |           |        |               AND ce3.timezone IS NULL                                                                      +|
     |           |        |               AND ce3.id != ce2.id                                                                          +|
     |           |        |               AND ce2.post_id IS NULL                                                                       +|
     |           |        |               AND ce3.post_id IS NULL                                                                       +|
     |           |        |   )                                                                                                         +|
     |           |        |                                                                                                              |
(2 rows)

これはこちらからのものです。

これは最新のマイグレーションが後者であることを示していますが、おそらくそのマイグレーションが追加されたばかりのプラグインからのものだからでしょう。

discourse=# SELECT version FROM schema_migrations ORDER BY version DESC LIMIT 1;
    version
----------------
 20250507013646
(1 row)

カレンダーイベントが大量にあります!!! 69,724,384個!

discourse=# select count(*) from calendar_events;
  count
----------
 69724384
(1 row)

それが問題のようですね。

. . . しかし、ソースサイトには discourse_calendar がインストールされていません!?

. . . しかし、ソーステーブルにその数のイベントが calendar_events にあります。 . . .

「いいね!」 1