「ERROR: canceling statement due the statement timeout」(エラー: ステートメントのタイムアウトにより、ステートメントをキャンセルしています) というエラーメッセージが表示される、失敗した AWS DMS タスクをトラブルシューティングするにはどうすればよいですか?

所要時間3分
0

AWS Database Migration Service (AWS DMS) を使用して、オンプレミスの PostgreSQL データベースとの間でデータを移行しています。AWS DMS タスクはしばらくの間正常に実行されますが、それからエラーで失敗します。このエラーをトラブルシューティングして解決するにはどうすればよいですか?

簡単な説明

PostgreSQL データベースが移行タスクのソースである場合、AWS DMS はフルロードフェーズでテーブルからデータを取得します。その後、AWS DMS は、変更データキャプチャ (CDC) フェーズで、レプリケーションスロットによって保持されている先書きログ (WAL) から読み取ります。

PostgreSQL データベースがターゲットである場合、AWS DMS はソースからデータを取得し、レプリケーションインスタンスに CSV ファイルを作成します。その後、AWS DMS はフルロードフェーズで COPY コマンドを実行し、それらのレコードをターゲットに挿入します。

ただし、トランザクション適用モードでは、AWS DMS は CDC フェーズでソースの WAL ログから正確な DML ステートメントを実行します。バッチ適用モードの場合、AWS DMS は CDC フェーズ中に CSV ファイルも作成します。その後、COPY コマンドを実行して正味の変更をターゲットに挿入します。

AWS DMS がソースからデータを取得するか、ターゲットにデータを配置することを試みる場合、デフォルトのタイムアウト設定である 60 秒が使用されます。ソースまたはターゲットが高負荷であるか、テーブルにロックがある場合には、AWS DMS は 60 秒以内にこれらのコマンドの実行を終了できません。そのため、タスクは失敗して、「canceling statement due to statement timeout」(ステートメントのタイムアウトにより、ステートメントをキャンセルしています) というエラーになり、ログに次のいずれかのエントリが表示されます。

メッセージ:

「]E: RetCode: SQL_ERROR SqlState: 57014 NativeError: 1 Message: ERROR: canceling statement due to statement timeout; Error while executing the query [1022502] (ar_odbc_stmt.c:2738)」(]E: RetCode: SQL_ERROR SqlState: 57014 NativeError: 1 メッセージ: エラー: ステートメントのタイムアウトによるステートメントのキャンセル。クエリ実行中のエラー [1022502] (ar_odbc_stmt.c:2738))

「]E: test_decoding_create_replication_slot(...) - Unable to create slot 'lrcyli7hfxcwkair_00016402_8917165c_29f0_4070_97dd_26e78336e01b' (on execute(...) phase) [1022506] (postgres_test_decoding.c:392))」(]E: test_decoding_create_replication_slot(...) - (実行(...) フェーズで)「lrcyli7hfxcwkair_00016402_8917165c_29f0_4070_97dd_26e78336e01b」のスロットを作成できませんでした [1022506] (postgres_test_decoding.c:392)))

これらのエラーをトラブルシューティングして解決するには、次のステップを実行します。

  • コマンドの実行時間が長くなる原因を特定します。
  • タイムアウト値を増やし、スロット作成タイムアウト値をチェックします。
  • スロット作成の問題をトラブルシューティングします。

解決方法

コマンドの実行時間が長くなる原因を特定する

タイムアウト期間中に実行できなかったコマンドを見つけるには、AWS DMS タスクログとタスクのテーブル統計セクションを確認します。この情報は、パラメータ log_min_error_statementERROR またはより低い重大度に設定されている場合は、PostgreSQL のエラーログファイルでも確認できます。失敗したコマンドを特定すると、失敗したテーブル名を見つけることができます。PostgreSQL エラーログの次のエラーメッセージ例を参照してください。

ERROR: canceling statement due to statement timeout 
STATEMENT: <The statement executed>"

関連付けられたテーブルのロックを見つけるには、ソースまたはターゲットで次のコマンドを実行します (エラーが表示される場所によって異なります)。

SELECT blocked_locks.pid AS blocked_pid,
 blocked_activity.usename AS blocked_user,
 blocking_locks.pid AS blocking_pid,
         blocking_activity.usename AS blocking_user, 
         blocked_activity.query    AS blocked_statement,
         blocking_activity.query   AS current_statement_in_blocking_process
   FROM  pg_catalog.pg_locks         blocked_locks 
    JOIN pg_catalog.pg_stat_activity blocked_activity  ON blocked_activity.pid = blocked_locks.pid
    JOIN pg_catalog.pg_locks         blocking_locks 
        ON blocking_locks.locktype = blocked_locks.locktype 
        AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
        AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
        AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
        AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
        AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
        AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
        AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
        AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
        AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
        AND blocking_locks.pid != blocked_locks.pid 
    JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
   WHERE NOT blocked_locks.GRANTED;

ブロックされている PID が見つかった場合は、次のコマンドを実行して、ブロックされた PID を停止または終了します。

SELECT pg_terminate_backend(blocking_pid);

デッド行または「タプル」は SELECT 時間を増やす可能性があるため、次のコマンドを実行してソーステーブルに多数のデッド行がないか確認します。

select * from pg_stat_user_tables where relname= 'table_name';

失敗したターゲットテーブルにプライマリキーまたは一意のインデックスがあるかどうかをチェックします。テーブルにプライマリキーや一意のインデックスがない場合は、UPDATE ステートメントの実行中にテーブルのフルスキャンが実行されます。このテーブルスキャンには長い時間がかかる場合があります。

タイムアウト値を増やす

AWS DMS は、ソースエンドポイントとターゲットエンドポイントの両方で、executeTimeout という追加の接続属性を使用します。executeTimeout のデフォルト値は 60 秒であるため、クエリの実行に 60 秒を超える時間がかかる場合、AWS DMS はタイムアウトします。

エラーが Source_Unload または Source_Capture に表示される場合は、ソースの executeTimeout のタイムアウト値を設定します。エラーが Target_Load または Target_Apply に表示される場合は、ターゲットの executeTimeout のタイムアウト値を設定します。次のステップに従って、タイムアウト値の設定を増やします。

1.    AWS DMS コンソールを開きます。

2.    ナビゲーションペインから [Endpoints] (エンドポイント) を選択します。

3.    PostgreSQL エンドポイントを選択します。

4.    [Actions (アクション)] を選択し、[Modify (変更)] を選択します。

5.    [Endpoint-specific settings] セクションを展開します。

6.    [Extra connection attributes] (追加の接続属性) のフィールドに、次の値を入力します。

executeTimeout=3600;

7.    [Save] (保存) を選択します。

8.    [Endpoints (エンドポイント)] ペインで、PostgreSQL エンドポイントの名前を選択します。

9.    [Connections] (接続) セクションで、エンドポイントの [Status] (ステータス) が [Testing] (テスト中) から [Successful] (成功) に変わります。

PostgreSQL DB インスタンスの statement_timeout パラメータを増やします (ミリ秒単位)。デフォルト値は 0 で、クエリのタイムアウトはオフになります。lock_timeout パラメータを増やすこともできます。デフォルト値は 0 で、ロックのタイムアウトはオフになります。

スロット作成の問題をトラブルシューティングする

PostgreSQL データベースでレプリケーションスロットを作成したときにタイムアウトが発生した場合は、次のようなログエントリが表示されます。

メッセージ

「]E: test_decoding_create_replication_slot(...) - Unable to create slot 'lrcyli7hfxcwkair_00016402_8917165c_29f0_4070_97dd_26e78336e01b' (on execute(...) phase) [1022506] (postgres_test_decoding.c:392)」(]E: test_decoding_create_replication_slot(...) - (実行(...) フェーズで)「lrcyli7hfxcwkair_00016402_8917165c_29f0_4070_97dd_26e78336e01b」のスロットを作成できませんでした [1022506] (postgres_test_decoding.c:392))

このタイムアウトは、[Task settings] (タスク設定) セクションの TransactionConsistencyTimeout パラメータを設定することで増やすことができます。デフォルト値は 600 秒です。

データベースユーザーテーブルにアクティブなロックがある場合、PostgreSQL はレプリケーションスロットを作成できません。次のコマンドを実行してロックを確認します。

select * from pg_locks;

その後、エラーが解決されたかどうかをテストするため、次のコマンドを実行して、ソースの PostgreSQL データベースにレプリケーションスロットを手動で作成します。

select  xlog_position FROM pg_create_logical_replication_slot('<Slot name as per
    the task log>', 'test_decoding');

それでもコマンドでスロットを作成できない場合は、PostgreSQL DBA を操作してボトルネックを特定し、データベースを設定する必要がある場合があります。コマンドが成功したら、テストとして作成したスロットを削除します。

select pg_drop_replication_slot(‘<slot name>');

最後に、移行タスクを再開します。


関連情報

クライアント接続のデフォルトに関する PostgreSQL のドキュメント

AWS DMS のターゲットとして PostgreSQL を使用する場合の追加の接続属性

DMS ソースとして PostgreSQL を使用する場合の追加の接続属性

Using a PostgreSQL database as an AWS DMS source (AWS DMS のソースとしての PostgreSQL データベースの使用)

AWS公式
AWS公式更新しました 2年前
コメントはありません

関連するコンテンツ