運用トラブルを防止するVACUUMのチューニング ~ XID / MXID周回問題と性能影響を防ぐ ~

PostgreSQLには、同時実行制御においてデータの一貫性を維持するために、各レコードにトランザクションID(XID)もしくはマルチトランザクションID(MXID)を付与して管理する仕組みがあります。このトランザクションIDには上限がありサイクリックに使用されるため、VACUUM機能によって古いトランザクションIDを回収し、再利用可能とする仕組み(凍結処理)があります。VACUUMはデフォルトで自動的に実施することができます。
しかし、頻繁にレコードを更新する業務などトランザクションIDを大量に発生する場合には、VACUUMによる凍結処理が追いつかず、データベースが新しいトランザクションIDの割り当てを中断し、INSERTやUPDATE、SELECT FOR UPDATEなど、トランザクションIDの割り当てを伴うトランザクションはエラー終了します(以降、周回問題と呼びます)。より高い業務継続性を実現するためには、VACUUM処理の実行多重度や実行頻度のチューニングが重要です。また、このチューニングは運用中の業務に影響を与えないよう対策する必要があります。

本記事では、PostgreSQL内部メカニズムを踏まえ、VACUUM処理の種類や使い分け、監視方法、および効果的なチューニング方法を解説します。

1. XID / MXID周回問題に対するVACUUMの働き

1.1 トランザクションID(XID) / マルチトランザクションID(MXID)と周回問題

PostgreSQLでは、トランザクションの可視性管理と並行処理におけるロック管理のために、トランザクションID(XID)とマルチトランザクションID(MXID)という2種類の識別子が用いられています。これらのIDは有限であるため、それぞれに周回問題が存在し、適切に管理されないとデータの整合性に影響を及ぼす可能性があります。

トランザクションID(XID)

XIDとは、トランザクションごとに自動で割り振られる識別子です。
テーブルの各行にはXIDを管理する列が存在し、挿入や更新されたときのXIDが記録されます。現在のXIDの値を基準にして、それ以前を過去のXID(可視の状態)とし、未来に実行されるトランザクションのXIDは不可視の状態として識別することで、他のトランザクションからの可視化の判断に利用されます。
XIDには32ビットの符号なし整数を使用しているため、約40億個(2の32乗個)のトランザクションが稼働すると、周回して0から割り振られます。また、現在のXIDの値を基準にして、それ以前の約20億個(XID全体の半分)を過去のXID、約20億先までを未来のXIDとして識別します。このため、現在のXIDから約20億個よりも前の古いXIDを持つレコードが存在すると、そのXIDが未来のXIDとして識別されて参照できなくなり、データの整合性が損なわれるXID周回問題が発生します。

マルチトランザクションID(MXID)

PostgreSQLは、XIDによる基本的な可視性管理に加え、複数のトランザクションが同じ行を同時にロックするような複雑な状況を効率的に扱うために、マルチトランザクションID(MXID)という仕組みも利用しています。
MXIDとは、複数のトランザクションが同時に同じ行(タプル)をロックする状況を効率的に管理するための特別な識別子です。具体的には、SELECT FOR SHAREのような共有ロックを取得する操作において、複数のトランザクションが同時に同じ行(タプル)をロックすると、PostgreSQLはこれらのトランザクションを一つのマルチトランザクションIDにまとめます。これにより、各トランザクションが個別にロック情報を保持するよりも、ロックの所有者を効率的に管理できます。
MXIDもXIDと同様に32ビットの有限な整数であるため、周回し、適切に管理されないと枯渇する可能性があります。このMXIDの枯渇も、XIDの枯渇と同様にデータの整合性を損なうXMID周回問題を引き起こします。

XID / MXID周回問題への対処法

これらのXIDおよびMXID周回問題への対処法として、PostgreSQLではVACUUMによるXIDおよびMXIDの凍結処理が用いられます。凍結処理は、古いXIDやMXIDを特別な値に置き換えることで、それらが未来のIDと誤認されることを防ぎ、実質的に再利用可能とします。

XID周回問題とVACUUMによる凍結処理については、以下の記事に詳しく解説しています。

Loading component...

Loading component...

Loading component...

また、XID周回問題が発生するまでに残り300万トランザクション(注1)を切ると、新しいトランザクションはエラーとなります。

Loading component...

Loading component...

1.2 VACUUMの種類と違い

VACUUMによるXID回収の手法には、大きく以下の2つがあります。ここでは、各手法の特徴について説明します。

  • autovacuum
  • 手動VACUUM(vacuumdbコマンド、またはSQL実行)

Loading component...

Loading component...

Loading component...

注2:autovacuum_vacuum_thresholdとautovacuum_vacuum_scale_factorから算出される値
注3:autovacuum_freeze_max_ageの値
注4:autovacuum_multixact_freeze_max_ageの値
注5:テーブルは、PostgreSQLが「実行契機」より自動で特定

1.3 XID枯渇によるユーザー影響の事例

XID枯渇によりユーザー影響が発生した事例をご紹介します。

Loading component...

Loading component...

Loading component...

Loading component...

2. VACUUM運用の監視と対策

2.1 VACUUM運用の監視項目

現在運用中のシステムにおいてXID周回問題が発生する可能性があるか確認するために、以下を監視してください。

Loading component...

2.2 監視項目の評価と対策

上記で監視した項目を評価し、対策が必要か確認してください。

Loading component...

Loading component...

Loading component...

【補足】

Loading component...

Loading component...

3. VACUUM運用のチューニング

以下に、本章で説明するVACUUM運用のチューニングの流れを示します。

Loading component...

3.1 autovacuumのチューニング

Loading component...

Loading component...

注8:VACUUMではI/O回数に応じてコストを計上し、規定値に到達した場合にスリープします。このときのコスト規定値とスリープ時間をpostgresql.confで設定することにより頻度をチューニングします。

Loading component...

Loading component...

Loading component...

3.1.3 autovacuumのチューニングによる影響の監視

autovacuumの動作を変更した場合には、「2.1 VACUUM運用の監視項目」の監視に加え、以下を監視してください。監視項目と監視方法を記述します。

Loading component...

Loading component...

3.1.4 監視結果の評価と対策

autovacuumチューニング時の監視項目に対する評価方法と対策について、以下に記述します。

Loading component...

Loading component...

Loading component...

3.2 手動VACUUMの設計とチューニング

Loading component...

Loading component...

Loading component...

Loading component...

Loading component...

Loading component...

3.2.3 手動VACUUM運用の監視

手動VACUUM運用時には、以下を監視してください。監視項目と監視方法を記述します。

Loading component...

3.2.4 監視結果の評価と対策

手動VACUUM運用時の監視項目に対する評価方法と対策について、以下に記述します。

Loading component...

Loading component...

2025年9月8日更新

富士通のソフトウェア公式チャンネル(YouTube)

富士通のミドルウェア製品のご紹介や各種イベント・セミナーの講演内容、デモンストレーションなどの動画をご覧いただけます。

Loading component...

Loading component...