🎯 本記事の趣旨
PostgreSQL 16以降をLinux環境に導入する際、表領域(tablespace)に使うファイルシステムは ext4 にしておいた方が安全かもしれません。
実際に私の現場で発生した不可解なエラーをきっかけに、XFS+PostgreSQLの落とし穴を調査・回避した内容を共有します。
🧭 発端:突然の「No space left on device」エラー
私が開発を担当している SaaS「XD.GROWTH」では、データ基盤としてPostgreSQLの拡張である Citus を使っております。
メンテナンス中、100GB超のCSVファイルを COPY
コマンドでインポートしていた際、次のようなエラーが発生しました。
ERROR: could not extend file "pg_tblspc/16386/PG_17_202406281/16392/9451674" with FileFallocate(): No space left on device
しかし、このときのディスク状況は以下の通り:
- ディスク使用率:50%未満
- 空き領域:約3TB
つまり、本当に「No space」な状況ではなかったのです。
🖥 エラーが発生した環境
項目 | 内容 |
---|---|
OS | RockyLinux 9.3 |
PostgreSQL | 17.2 |
ファイルシステム | XFS |
🔎 エラー原因の調査プロセス
-
FileFallocate()とは?
→ PostgreSQL内部で定義されている関数で、実体はposix_fallocate()
を呼び出しています。 -
posix_fallocate()の役割は?
→ 指定されたファイル領域を事前に確保(sparse領域回避)するシステムコールです。
→ 空き容量が不足している場合、posix_fallocate()
はENOSPC
というエラーコードを返します。 -
「空きがあるのにENOSPC」がposix_fallocate()で報告されることはあるのか?
→ 調査の結果、XFSファイルシステムとの組み合わせで実際に発生することがわかりました。
🧠 わかったこと:XFS+posix_fallocate() の落とし穴
XFSで posix_fallocate()
を使うと、空き容量があっても ENOSPC
を返すことがあることがわかりました。
原因として考えられるのは以下のとおりです:
- ✅ メタデータ領域の不足
- ✅ アロケーション単位の断片化
- ✅ 使用できない予約領域の確保失敗
- ✅ クォータ制限
今回のケースでは、メタデータ・予約領域・クォータの影響は除外できたため、
おそらく「アロケーション単位の断片化」が原因と考えられます。
🛠 対応方法:ext4への切り替え
ファイルシステムがXFSの場合に発生する問題なので、下記の「関連する報告・事例」にあるPostgreSQLコミュニティの報告を参考に、表領域をext4に再作成し、再インポートすることで問題を回避しました。
以降、同様のエラーは発生していません。
🗂 関連する報告・事例
以下のように、PostgreSQLコミュニティやディストリビューションのバグ報告でも類似の事例が複数報告されています。
-
PostgreSQL ML: FileFallocate misbehaving on XFS
https://www.postgresql.org/message-id/CADofcAV8xu3hCNHq7-7x56KrP9rD6%3DA04%3DqjTr3nETh-gptF8w%40mail.gmail.com -
Ubuntu Launchpad: XFSのfallocateが誤ってENOSPCを返す
https://bugs.launchpad.net/bugs/1791323 -
Red Hat Bugzilla: XFSのfallocateが誤ったerrnoを返す問題
https://bugzilla.redhat.com/show_bug.cgi?id=544349
📌 補足:-o inodes64
マウントオプションについて
PostgreSQL ML(2025年5月11日の報告)では、
「XFSでも
-o inodes64
を付けてマウントすれば、この問題を回避できた」
という報告もあります。
✅ inodes64
とは?
- XFSのinode番号を64bit拡張するマウントオプション
- 断片化や割り当てエラーの一部を回避できる可能性がある
⚠ 懸念点
- 古い32bitアプリケーションとの互換性に注意(rsyncやNFSクライアントなど)
- サーバー内の他アプリケーションへの影響を事前確認するのが安全
📚 PostgreSQLにおけるFileFallocateの導入時期
-
FileFallocate()
は PostgreSQL 16以降 で導入されました。 -
COPY
や大きな書き込み処理時に、事前に領域を確保するために使われます。 - PostgreSQL 16以前 の場合、
FileFallocate()
は使われておらず書き込み前にディスクの領域確保は行わないので、空き容量があるのに「No space left on device」というエラーは発生しません。
✅ まとめ
項目 | 内容 |
---|---|
エラー内容 | No space left on device(空き3TBなのに) |
原因 | XFS + posix_fallocate() による断片化エラー |
対応 | ext4ファイルシステムに切り替え |
補足 |
-o inodes64 マウントでも回避可能な事例あり |
✍ おわりに
PostgreSQL 16以降を導入する際、XFSを使っている場合は表領域での断片化やposix_fallocate()
の挙動に注意が必要です。
特に巨大なデータを扱うシステムでは、ext4を選ぶことでリスクを回避できる可能性があります。
同様のトラブルに遭遇した方の参考になれば幸いです。