Postgresには、現在のトランザクションIDの前後に約20億トランザクションが有効になっている移動イベントホライズンが含まれています。現在のトランザクションIDより最大20億前、または20億以上遅れているトランザクションは将来と見なされるため、現在のトランザクションからは見えなくなります。
Postgresは、古い行を特別にマークして、現在のトランザクションIDとの関係でどこにいても表示されるようにすることで、この壊滅的なデータ損失を回避します。
フリーズとは、古いライブタプル(つまり、データベースの行)にマークを付けて、将来のように見える移動イベントの範囲にひかれないようにするプロセスです。これは、トランザクションからは見えなくなった古い死んだタプルによって消費されたスペースを解放するバキュームとは対照的です。
どちらのプロセスも真空によって管理されます。
フリーズの実行方法を管理する設定は多数あります。
まず、vacuum_freeze_min_age
バキュームがすでにページを調べて、クリーンアップできるデッドタプルがあるかどうかを確認しているときに、タプルがフリーズするかどうかを制御します。 vacuum_freeze_min_age
より古いタプル この場合、凍結されます。これを低く設定すると、後で行う作業が少なくなりますが、CPUとIOまたはWALアクティビティの両方で余分な労力がかかる可能性があります。一般に、このセットを少なくとも数時間のトランザクションに設定する必要があります。持続的なレートとして、1秒あたり最大2000のトランザクションを実行することを期待しているとします。 2000 TPSは、1時間あたり720万トランザクションです。したがって、この場合のかなり積極的な設定は、20mと言うことができます。デフォルト設定は50mです。同様にvacuum_multixact_freeze_min_age
の場合 。 transaction_idカウンターとmultixidカウンターは独立していることに注意してください。両方を追跡する必要があります。
次に、vacuum_freeze_table_age
があります およびvacuum_multixact_freeze_table_age
。これらの設定は、自動バキュームがデッド行を含む可能性のあるページだけでなく、フリーズされていない行を含む可能性のあるページをいつ表示するかを管理します。これらの設定のデフォルトは150mです。 vacuum_freeze_min_age
を減らした場合 十分に、多くの場合、このより積極的な真空は、行うべき作業がほとんどまたはまったくありません。いずれにせよ、Postgresの最新バージョン(9.6以降)はすべてのタプルがフリーズされているページのマップを保持し、すべてがフリーズされていないページにのみアクセスするため、このプロセスは以前ほど忙しくありません。これは、これが全表スキャンではなくなったことを意味します。
最後にautovacuum_freeze_max_age
があります 。凍結されていない行がないかテーブルが最後に完全にスキャンされたのがこれだけ前のトランザクションよりも多かった場合、autovacuumはテーブルのラップアラウンド防止バキュームを開始します。デフォルトは200mです。同様に、autovacuum_multixact_freeze_max_age
の場合 デフォルトは400mです。これは本当に避けたいものです。できることは2つあります。まず、これらの設定を10億程度に増やすことは非常に一般的であり、特にトランザクションの消費量が多いシステムでは、余裕を持たせることができます。もっと作ることもできますが、最も古いタプルと事象の地平線の間に十分なトランザクションスペースが必要です。次に、データベースがこれに遭遇する前に、システムを監視し、是正措置を講じることが重要です。この是正措置には、多くの場合、手動による真空引きが含まれます。
発生する可能性のある問題の1つは、通常の(つまり、アンチラップアラウンドではない)自動バキュームが自動的にキャンセルされるDDLがある場合です。これを十分に行うと、最終的にはアンチラップアラウンドバキュームが強制され、すべてのDDLがバキュームプロセスの背後でキューに入れられ、それ以降のDMLがブロックされます。この段階では、バキュームが終了するまでテーブルを事実上読み取ることができません。これはデータベースの使用パターンによって異なりますが、これは単なる理論上の可能性ではなく、PostgresのデプロイメントとDBAはそれを考慮する必要があります。
これを管理するには、データベースクラスターを監視することが重要です。特に、datfrozenxid
を監視する必要があります およびdatminmxid
クラスター内の各データベースの数を増やし、これらが古すぎる場合は、ラップアラウンド防止バキュームが必要になる前に修復アクションを実行します。多くの場合、問題はデータベース内の1つまたはいくつかのテーブルにあります。 relfrozenxid
を調べると、どれが問題であるかを見つけることができます。 およびrelminmxid
データベース内のテーブルの。 age()
およびmxid_age()
関数は、トランザクションIDとmultixidカウンターのそれぞれの経過時間を検出するのに役立ちます。
フリーズは回避できるものではなく、積極的に管理する必要があるPostgresの重要なメンテナンスアクティビティです。