Aurora PostgreSQL 互換のトランザクションの ID ラップアラウンドをトラブルシューティングする方法を教えてください。
Amazon Aurora PostgreSQL 互換エディションのデータベース (DB) クラスターにおけるトランザクションの ID ラップアラウンドの問題をトラブルシューティングしたいと考えています。
解決策
メトリクスと CloudWatch アラームをモニタリングして問題を防ぐ
バキューム処理されていない最も古いトランザクションの経過時間をモニタリングするには、Amazon CloudWatch の MaximumUsedTransactionIDs メトリクスを確認してください。トランザクションの ID ラップアラウンド問題を防ぐには、CloudWatch アラームを作成します。詳細については、「Implement an early warning system for transaction ID wraparound in Amazon Relational Database Service (Amazon RDS) for PostgreSQL」(Amazon Relational Database Service (Amazon RDS) for PostgreSQL におけるトランザクション ID ラップアラウンドの早期警告システムの実装) を参照してください。
診断クエリを実行する
psql または pgAdmin を使用して PostgreSQL DB インスタンスに接続します。
データベースの経過時間を確認するには、次のコマンドを実行します。
SELECT datname, age(datfrozenxid) FROM pg_database ORDER BY 2 DESC LIMIT 20;
注: rdsadmin または template0 データベースのトランザクション ID が最も古い経過期間を示している場合は、AWS サポートに連絡してください。
経過期間が最も長いデータベースに接続して、テーブルに関する潜在的な問題を特定するには、次のコマンドを実行します。
SELECT c.relnamespace::regnamespace as schema_name, c.oid::regclass as table_name, greatest(age(c.relfrozenxid),age(t.relfrozenxid)) as age, pg_size_pretty(pg_table_size(c.oid)) as table_size, t.relkind, t.relpersistence FROM pg_class c LEFT JOIN pg_class t ON c.reltoastrelid = t.oid WHERE c.relkind IN ('r', 'm') ORDER BY 3 DESC LIMIT 20;
経過時間が長いテーブルの自動バキューム履歴を確認するには、次のコマンドを実行します。
SELECT relname, n_live_tup, n_tup_upd, n_tup_del, n_dead_tup, last_vacuum, last_autovacuum, last_analyze, last_autoanalyze FROM pg_stat_user_tables WHERE relname='table_name';
注: table_name は、実際のテーブル名に置き換えてください。
アクティブなバキューム操作をモニタリングするには、次のコマンドを実行します。
SELECT datname, usename, pid, state, wait_event, current_timestamp - xact_start AS xact_runtime, query FROM pg_stat_activity WHERE upper(query) LIKE '%VACUUM%' AND pid <> pg_backend_pid() ORDER BY xact_start;
自動バキューム処理のブロック要因を解決する
次の Aurora PostgreSQL 互換バージョンのいずれかを使用している場合は、「Aurora PostgreSQL で積極的なバキュームのブロック要因を特定して解決する」を参照してください。
- 13.19 以降
- 14.16 以降
- 15.11 以降
- 16.7 以降
- 17.2 以降
実行時間が長いトランザクションを解決する
長時間実行されているトランザクションやアイドル状態の移行中セッションでは、自動バキュームがブロックされる可能性があります。
PostgreSQL エラーログに次の警告メッセージが表示されます。
"WARNING: oldest xmin is far in the past HINT: Close open transactions soon to avoid wraparound problems."
自動バキュームをブロックしているトランザクションを特定するには、次のコマンドを実行します。
SELECT pid, age(backend_xid), substr(query,1,20), extract(epoch from now()) - extract(epoch from xact_start) as duration, state FROM pg_stat_activity WHERE xact_start is not null AND age(backend_xid) is not null ORDER BY 2 DESC LIMIT 10;
この問題を解決するには、アクティブなクエリをキャンセルするか、接続を切断します。
アクティブなクエリをキャンセルするには、次のコマンドを実行します。
SELECT pg_cancel_backend(pid);
注: pid を、クエリ結果のプロセス ID に置き換えてください。
アイドル状態の接続を切断するには、次のコマンドを実行します。
SELECT pg_terminate_backend(pid);
注: pid を、クエリ結果のプロセス ID に置き換えてください。
長時間実行されているトランザクションが自動バキュームを再びブロックしないようにするには、 statement_timeout、idle_in_transaction_session_timeout、log_min_duration_statement パラメータを設定します。
非アクティブな論理レプリケーションスロットを解決する
非アクティブなスロットを特定するには、次のコマンドを実行します。
SELECT slot_name, slot_type, database, xmin, catalog_xmin, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(),restart_lsn)) AS replicationSlotLag, active FROM pg_replication_slots ORDER BY age(xmin), age(catalog_xmin) DESC;
警告: レプリケーションスロットを削除する前に、そのスロットに実行中のレプリケーションがなく、非アクティブかつ回復不可能な状態であることを確認してください。レプリケーションが進行中で、アクティブかつ回復可能なスロットを削除すると、複製が中断されたり、データが失われたりする可能性があります。
使われていないスロットを削除するには、次のコマンドを実行します。
SELECT pg_drop_replication_slot('slot_name');
注: slot_name をレプリケーションスロット名に置き換えてください。
リーダーインスタンスの問題を解決する
ホットスタンバイフィードバックを妨げ、自動バキュームをブロックしている可能性のある Aurora クラスター内のリーダーを特定するには、次のクエリを実行します。
select server_id, feedback_epoch, feedback_xmin from aurora_replica_status() WHERE (feedback_xmin IS NOT NULL AND feedback_xmin > 0)
グローバルデータベースクラスターのホットスタンバイフィードバックを妨げているリーダーに対して、次のクエリを実行します。
select server_id,aws_region,feedback_epoch,feedback_xmin from aurora_global_db_instance_status () WHERE (feedback_xmin IS NOT NULL AND feedback_xmin > 0);
feedback_epoch と feedback_xmin の合計値が最も小さいリーダーインスタンスで、次のクエリを実行します。
SELECT pid, age(backend_xid), substr(query,1,20), extract(epoch from now()) - extract(epoch from xact_start) as duration, state FROM pg_stat_activity WHERE backend_xmin::text::bigint =feedback_xmin
注: feedback_xmin を上記のクエリ結果の feedback_xmin 値に置き換えてください。
安全に実行できる場合は、pg_terminate_backend(pid) を使用して長時間実行されているトランザクションを終了します。
コミットされていない準備済みトランザクションを解決する
準備済みトランザクションを特定するには、次のコマンドを実行します。
SELECT database, gid, prepared, owner, database, transaction::text::bigint as xid, now() - prepared AS time_since_prepared FROM pg_prepared_xacts ORDER BY age(transaction) DESC;
準備済みトランザクションを解決するには、準備済みのトランザクションをコミットするか、ロールバックします。
準備済みトランザクションをコミットするには、次のコマンドを実行します。
COMMIT PREPARED 'gid'
注: gid をクエリ結果のグローバルトランザクション ID に置き換えてください。
警告: 準備済みトランザクションをロールバックする前に、そのトランザクションが分散トランザクションシーケンスの一部ではないことを確認してください。
準備済みトランザクションをロールバックするには、次のコマンドを実行します。
ROLLBACK PREPARED 'gid'
注: gid をクエリ結果のグローバルトランザクション ID に置き換えてください。
孤立した一時テーブルを解決する
PostgreSQL の自動バキュームプロセスが孤立した一時テーブルを検出すると、次のイベントがログに記録されます。
LOG: autovacuum: found orphan temp table "%s"."%s" in database "%s"
孤立した一時テーブルを特定するには、次のコマンドを実行します。
SELECT oid, relname, relnamespace::regnamespace, age(relfrozenxid) FROM pg_class WHERE relpersistence = 't' ORDER BY age(relfrozenxid) DESC;
一時テーブルを削除するには、次のコマンドを実行します。
DROP TABLE temporary_table
注: temporary_table を実際の一時テーブル名に置き換えてください。
バキュームのパフォーマンスに関する問題を解決する
自動バキュームの実行が遅いと、フリーズ操作が遅延することがあります。
この問題を解決するには、最初に autovacuum_max_workers パラメータを増やして、より多くのバキューム操作を同時実行できるようにします。次に、次の式を使用して autovacuum_vacuum_cost_limit パラメータを均等に増やします。
Individual worker's cost_limit = autovacuum_vacuum_cost_limit / autovacuum_max_workers
パラメータを増やしてもバキュームのパフォーマンスが不十分な場合は、Amazon RDS インスタンスを、より多くの vCPU を持つクラスにアップグレードしてください。autovacuum_vacuum_cost_delay パラメータをテーブルレベルで変更すると、自動バキューム操作を高速化できます。
autovacuum_vacuum_cost_delay パラメータをテーブルレベルで変更するには、次のコマンドを実行します。
ALTER TABLE mytable SET ( autovacuum_vacuum_cost_delay = value, autovacuum_vacuum_cost_limit = value );
注: mytable をテーブル名に、value を目的のパラメータ値に置き換えてください。
大規模なインデックスに対するバキュームのパフォーマンス
大規模なインデックスをバキュームする場合、メモリ制約により同じインデックスに複数のパスが強制され、VACUUM の合計時間が大幅に長くなる可能性があります。
PostgreSQL 16 以前で大規模なインデックスで VACUUM 操作が遅い場合は、以下の原因が考えられます。
- インデックスサイズが 1 GB を超えている。
- 複数の VACUUM パスが発生している。パスの数を表示するには、pg_stat_progress_vacuum から index_vacuum_count をクエリします。
- maintenance_work_mem または autovacuum_work_mem の設定が間違っている。
この問題を解決するには、次の操作を実行します。
- 未使用または重複するインデックスを削除する。
- maintenance_work_mem または autovacuum_work_mem を増やす。新しいメモリ設定を有効にするには、現在自動バキュームを実行しているプロセスを終了してください。
- VACUUM FREEZE 操作を手動で実行し、セッション内の maintenance_work_mem を増やす。
PostgreSQL バージョン 12 以降を使用している場合は、次のコマンドを実行して、インデックスを除外した手動バキュームの可能性を確認してください。
VACUUM (INDEX_CLEANUP FALSE, VERBOSE TRUE) table_name;
注: table_name は、実際のテーブル名に置き換えてください。
論理不整合
論理的に不整合なインデックスが自動バキュームプロセスをブロックすると、次のいずれかのエラーメッセージが表示されることがあります。
- ERROR: right sibling's left-link doesn't match:block 5 links to 10 instead of expected 2 in index ix_name
- ERROR: failed to re-find parent key in index "XXXXXXXXXX" for deletion target page XXX CONTEXT: while vacuuming index index_name of relation schema.table
この問題を解決するには、インデックスを再構築してください。または、PostgreSQL バージョン 12 以降の場合は、インデックスのクリーンアップをスキップできます。
インデックスを再構築するには、次のコマンドを実行します。
REINDEX INDEX ix_name CONCURRENTLY;
注: ix_name を実際のインデックス名に置き換えてください。
または
PostgreSQL 12 以降のインデックスのクリーンアップをスキップするには、次のコマンドを実行します。
VACUUM FREEZE INDEX_CLEANUP FALSE table_name;
注: table_name は、実際のテーブル名に置き換えてください。
関連情報
Preventing transaction ID wraparound failures (トランザクション ID のラップアラウンドエラーの防止)(PostgreSQL ウェブサイト)
Amazon Aurora PostgreSQL での PostgreSQL 自動バキュームの使用
Understanding autovacuum in Amazon RDS for PostgreSQL environments (Amazon RDS 環境の PostgreSQL 自動バキュームについて)
Amazon RDS for PostgreSQL または Aurora PostgreSQL 互換 DB インスタンスで、長時間実行しているクエリを終了させる方法を教えてください
