Handling replication apply errors#

レプリケーションの適用に障害が発生すると、PGDはデフォルトで失敗したトランザクションを無期限に再試行します。永続的な障害は、適用の繰り返しによるシステムの過負荷と、繰り返しのエラーメッセージでログを埋める可能性があります。

apply_error_policy ノードグループオプションを使用して、トランザクションの適用に失敗した場合のPGDの動作を制御します。設定した回数の試行後に再試行を停止し、レビューのために失敗した変更を記録し、サブスクリプションを無効にするか、失敗したトランザクションをスキップしてレプリケーションを続行するように設定します。

エラーポリシーの選択#

4つのエラーポリシーが使用でき、ノードグループレベルで構成されます。

  • ``keep_retrying`` は、失敗したトランザクションを無期限に再試行します。 PGDはサイレントに再試行し続け、何も記録されず、サブスクリプションが無効になることはありません。一時的なロック競合など、自己修復が予想される一時的な障害に使用します。 keep_retrying がデフォルトです。

  • ``disable_after_retries`` apply_error_max_retries 回まで再試行し、サブスクリプションを無効にして、理由を記録します。障害が無期限に持続することはできないが、一時的なものである可能性がある場合に使用します。

  • ``record_all_and_disable`` は、失敗したトランザクションを完全に記録し、サブスクリプションを無効にします。レプリケーションを停止する前に、何が失敗したかの完全な記録が必要な場合に使用します。

  • ``record_all_and_skip`` は、失敗したトランザクションを完全に記録し、スキップして、レプリケートを続行します。サブスクリプションは有効なままですが、失敗した変更はbdr.pending_failed_changes にサイレントに蓄積されます。すべてのトランザクションが適用されることを保証するよりも継続性が重要な高可用性展開に使用します。

record_all_and_disable およびrecord_all_and_skip ポリシーは、アクションを実行する前にキャプチャ専用モードで再生することにより完全なトランザクションをキャプチャし、後で検査および解決するための完全なレコードを提供します。

エラーポリシーの構成#

bdr.alter_node_group_option を使用してノードグループにポリシーを設定します。ノードグループ名を見つけるには

SELECT node_group_name FROM bdr.local_node_summary;

選択したポリシーを適用します。

SELECT bdr.alter_node_group_option(
    top_group,
    apply_error_policy,
    record_all_and_disable
);

必要に応じて、サポートパラメーターを構成します。例

- - Retry attempts before the policy takes action (default: 3)
SELECT bdr.alter_node_group_option(
    top_group,
    apply_error_max_retries,
    5
);

- - Maximum transactions record_all_and_skip can auto-skip before disabling.
- - Set to -1 for unlimited. Default is NULL (unlimited).
SELECT bdr.alter_node_group_option(
    top_group,
    apply_error_max_skips,
    100
);

- - Maximum bytes to capture per failed transaction (default: 10485760, which is 10 MB)
SELECT bdr.alter_node_group_option(
    top_group,
    apply_error_max_record_size,
    52428800
);

適用エラーグループオプションの完全なリストについては、 bdr.alter_node_group_option()を使用したグループ構成 を参照してください。

無効になったサブスクリプションへの対応#

サブスクリプションがdisable_after_retries またはrecord_all_and_disable ポリシーで無効になると、レプリケーションが停止します。次の手順に従って、障害を調査および解決します。

  1. 影響を受けるサブスクリプションとその理由を確認します。

SELECT sub_name, disable_reason, effective_error_policy, pending_changes
FROM bdr.subscription_error_status
WHERE NOT sub_enabled;

disable_reason 列は、PGDがサブスクリプションを無効にした理由を記録し、 pending_changes は、レビューを待機している失敗した変更の数を示します。完全な列リファレンスについては、 bdr.subscription_error_status を参照してください。

  1. 失敗した変更を確認します。

SELECT id, failed_txn_id, subscription_name, remote_xid, remote_commit_lsn,
       operation, qualified_table, sql_statement, error_message
FROM bdr.pending_failed_changes_sql
WHERE change_status = pending
ORDER BY id;
  1. オプションで、スキップしても安全かどうかを分析します。 bdr.format_skip_analysis は、スキップをSAFE 、UNSAFE 、またはUNKNOWN として分類し、その理由を説明します。

SELECT bdr.format_skip_analysis(id)
FROM bdr.pending_failed_changes
WHERE change_status = pending
LIMIT 1;
  1. bdr.resolve_failed_transaction を使用して解像度をプレビューします。デフォルトはdry_run := true です。

SELECT bdr.resolve_failed_transaction(
    bdr_mydb_mygroup_node1_node2,  -- subscription_name
    12345::xid,                    -- remote_xid
    0/1234567::pg_lsn,             -- remote_commit_lsn
    skipped,                       -- resolution: skipped, applied, or discarded
    true                             -- re_enable
);

または、3部分の識別子の代わりにfailed_txn_id bdr.pending_failed_changes からのUUIDを渡します。

  1. dry_run := false を渡して解決を実行します。

SELECT bdr.resolve_failed_transaction(
    bdr_mydb_mygroup_node1_node2,
    12345::xid,
    0/1234567::pg_lsn,
    skipped,
    true,   -- re_enable
    false   -- dry_run
);

すぐに再有効化せずに解決するには、準備ができたらre_enable := false を渡し、手動で再有効化します。

SELECT bdr.alter_subscription_enable(bdr_mydb_mygroup_node1_node2);
  1. リトライカウンターとスキップカウンターをリセットして、ポリシーしきい値が将来の障害に新しく適用されるようにします。

SELECT bdr.alter_subscription_reset_error_counters(bdr_mydb_mygroup_node1_node2);
  1. 解像度を確認したら、解決された行をbdr.pending_failed_changes から削除して、領域を再利用します。解像度の概要はbdr.resolved_transactions に保存されます。

DELETE FROM bdr.pending_failed_changes
WHERE change_status IN (skipped, applied);

個々の変更の解決#

失敗したトランザクションにさまざまな変更が含まれ、安全に解決できるものとそうでないものは、 bdr.skip_failed_change およびbdr.apply_failed_change を使用して、トランザクション全体ではなく個々の行を操作します。すべての変更を個別に解決したら、 bdr.resolve_failed_transaction を呼び出してサブスクリプションの位置を進め、再度有効にします。

切り捨てられたキャプチャの処理#

失敗したトランザクションがapply_error_max_record_size を超えると、PGDは可能な限り多くの変更を記録し、bdr.pending_failed_changes にcapture_truncated = true を設定します。レコードが不完全であるため、切り捨てられたトランザクションはbdr.apply_failed_transaction を使用して再適用できません。

切り捨てられたトランザクションを解決するには、 bdr.reconstruct_failed_transaction を使用して部分SQLを確認し、その出力を参照として使用してターゲットノードに完全なトランザクションを手動で適用してから、 bdr.skip_failed_transaction を使用してキャプチャされた変更をスキップとしてマークし、サブスクリプションを再度有効にします。

大規模なトランザクションでの切り捨てを防ぐには、次の障害の前にapply_error_max_record_size を増やします。

蓄積された障害の監視#

record_all_and_skip では、サブスクリプションは有効なままでレプリケーションは継続されますが、失敗したトランザクションはサイレントに蓄積されます。 bdr.subscription_error_status を定期的にチェックしてそれらをキャッチします。

SELECT sub_name, total_skips, pending_changes
FROM bdr.subscription_error_status;

pending_changes がゼロ以外の場合、 無効になったサブスクリプションへの対応 と同じ手順を使用して累積障害を確認および解決します。サブスクリプションがまだアクティブであるため、再有効化の手順をスキップします。

過去の決議を確認するには

SELECT subscription_name, origin_node, remote_xid, resolution,
       insert_count, update_count, delete_count, error_message, resolved_at
FROM bdr.resolved_transactions_info
ORDER BY resolved_at DESC;