スキップしてコンテンツを表示

AWS DMS タスクが失敗し、エラーメッセージ "ERROR: canceling statement due to statement timeout" が表示される場合のトラブルシューティング方法を教えてください。

所要時間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 コマンドを実行し、そのレコードをフルロードフェーズ中にターゲットに挿入します。

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

AWS DMS がソースからのデータ取得またはターゲットへのデータ配置を試行する際は、デフォルトのタイムアウト設定である 60 秒が適用されます。ソースまたはターゲットの負荷が高いか、テーブルにロックが発生している場合、AWS DMS はコマンドの実行を 60 秒以内に完了できません。結果的にタスクは失敗し、"canceling statement due to statement timeout," というエラーメッセージが表示されます。また、ログには次のいずれかのエントリが表示されます。

Messages:

"]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: 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))" (スロットの作成失敗)

エラーをトラブルシューティングして解決するには、次の手順を実行します。

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

解決策

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

タイムアウト期間中に実行できなかったコマンドを特定するには、AWS DMS タスクログ、およびそのタスクのテーブル統計情報セクションを確認します。パラメータ log_min_error_statement の深刻度が ERROR 以下である場合は、この情報は 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.ナビゲーションペインで [エンドポイント] を選択します。

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

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

5.[エンドポイント固有の設定] セクションを展開します。

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

executeTimeout=3600;

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

8.[エンドポイント] ペインで目的の PostgreSQL 名を選択します。

9.[接続] セクション内では、エンドポイントの [ステータス]Testing から Successful に変化します。

PostgreSQL DB インスタンスの statement_timeout パラメータは、ミリ秒単位で増やすことができます。デフォルト値である 0 では、すべてのクエリに対し、タイムアウトは無効です。lock_timeout パラメータを増やすこともできます。デフォルト値である 0 では、ロックに対するタイムアウトは無効です。

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

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

Messages

"]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)"

このタイムアウトを増やすには、[タスク設定] セクションの 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 ドキュメント

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

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

PostgreSQL データベースを AWS DMS のソースとして使用する

コメントはありません

関連するコンテンツ