Amazon Web Services ブログ

AWS DMS がフルロードおよび CDC タスクを開始する際にオープントランザクションをどのように扱うか

リレーショナルデータベース管理システム(RDBMS)における、consistency(一貫性 / 整合性)はトランザクションの重要な特性の1つです。一貫性は、トランザクションが終了した後にデータが常に正しい状態に保たれるためのルールを定義します。データの一貫性により、トランザクションはテーブルに対して事前に定義された予測可能な方法でのみ変更を加えることができ、これによりデータの整合性に対する意図しない影響を防ぐことができます。
データベース移行の際にシステム停止時間を最小限に抑えるためには、まずはじめに移行元のデータベースから整合性のとれたスナップショットを取得する必要があります。その後、移行元のデータベースとの整合性を保ちながらレプリケーションを確立するために、整合性のとれたスナップショットを取得した時点のトランザクション位置を記録する必要があります。基本的な考え方として、スナップショット取得時点からレプリケーション開始までの間にトランザクションの欠落や抜けがある場合、移行先のデータベースの整合性は保証されません。

AWS Database Migration Service (AWS DMS) は、リレーショナルデータベース、データウェアハウス、NoSQL データベース、およびその他のタイプのデータストアに対する移行を支援します。
初期データロード、または AWS DMS のフルロードフェーズ、および変更データキャプチャ (CDC) が一貫した状態から開始されるトランザクション位置を管理するために、AWS DMS は TransactionConsistencyTimeout というタスク設定を実装して、AWS DMS タスクの開始時にオープントランザクションを処理するようにしました。
この記事では、さまざまなエンジンのフルロード + CDC タスクの開始時に AWS DMS がオープントランザクションを処理する方法について説明し、consistency timeout(整合性タイムアウト)の問題を回避するためのベストプラクティスを紹介します。

トランザクション整合性タイムアウトに関するよくある質問

移行元のデータベースの種類によって、TransactionConsistencyTimeout に関して以下のような質問がよく寄せられます。

  • Oracle ソース – タスクを開始した時 Before load の状態で10分間も停止しているのはなぜですか。タスクログに表示される「open transaction」とは何を意味しますか。オープントランザクションのタイムアウトが発生するとどうなりますか。
  • SQL Server ソース – タスクを開始した時に、Before load の状態で停止しているのはなぜですか。
  • PostgreSQL ソースstatement_timeout を設定していないのに、タスクの開始時にステートメントのタイムアウトが発生してタスクが失敗したのはなぜですか。
  • MySQL ソース – 長時間トランザクションが存在する場合、フルロードや CDC タスクの開始に支障が出るのでしょうか。

これらの疑問に答えるため、まず AWS DMS でのオープントランザクションとは何かを説明します。

AWS DMS におけるオープントランザクション

AWS DMS におけるオープントランザクションとは、フルロード + CDC タスクの開始時点で、移行元のリレーショナルデータベースでコミットもロールバックもされていないトランザクションを指します。
前述した移行アプローチ同様、AWS DMS はフルロードを開始する際と、CDC のためのトランザクション位置を特定する際に、整合性のとれた状態を必要とします。
RDBMS エンジンごとにトランザクションログの実装方法が異なるため、AWS DMS も移行元の RDBMS によって異なる動作をします。以降のセクションでは、Oracle、SQL Server、PostgreSQL、MySQL を移行元とした場合に、AWS DMS がオープントランザクションをどのように処理するかについて説明します。

Oracle ソースからの移行時における AWS DMS のオープントランザクション処理について

フルロード + CDC タスクの場合、タスク設定 TransactionConsistencyTimeout は、AWS DMS がフルロードオペレーションを開始する前にトランザクションが終了するのを待つ秒数を定義します。デフォルト値は 600 秒(10 分)です。タスクの開始時にトランザクションが開いている場合、AWS DMS はデフォルトで 10 分間待機します。TransactionConsistencyTimeout 値に達すると、実行中のトランザクションがあってもフルロードが開始され、TransactionConsistencyTimeout よりも長いトランザクションが将来のレプリケーションで失われます。

次の図では、フルロードタスク + CDC タスクが開始されると、合計 6 つのトランザクションのうち、AWS DMS ソースキャプチャプロセスによって特定されるオープントランザクションが 2 つあります。

  • トランザクション 1 – ソースキャプチャが開始された時点ではオープントランザクションですが、TransactionConsistencyTimeout の時間枠内かつフルロードが開始される前にコミットされます。したがって、フルロードフェーズに含まれます。
  • トランザクション 2TransactionConsistencyTimeout の時間枠内およびフルロードが開始される前に開始およびコミットされます。したがって、フルロードフェーズに含まれます。
  • トランザクション 3 と 4 – フルロードフェーズ中にコミットされるため、キャッシュされた変更として、フルロードが終了した後に適用されます。
  • トランザクション 5 – フルロードフェーズで開始し、フルロードが完了した後にコミットされるため、CDC として、キャッシュされた変更が適用された後に適用されます。
  • トランザクション 6FailOnTransactionConsistencyBreached はデフォルトで false に設定されているため、タスクは続行されます。オープントランザクション B はスキップされ、TransactionConsistencyTimeout 後にコミットされたため、データが失われます。TransactionConsistencyTimeoutFailOnTransactionConsistencyBreached の設定に関するベストプラクティスについては、後のセクションで説明します。

次のログは、オープントランザクションがある場合の一般的な AWS DMS ログの例を示しています。SOURCE_CAPTURE コンポーネントはオープンされているトランザクションの数を識別し、SORTER は TransactionConsistencyTimeout の後にトランザクション整合性タイムアウトに関する警告を出力します。

xxxx-xx-xxT00:00:00 [SOURCE_CAPTURE  ]I:  Opened transaction list contains '6' transactions, these in-flight transaction(s) will not be copied  (oracle_endpoint_capture.c:967)
…
xxxx-xx-xxT00:00:00 [SORTER          ]I:  6 open transactions. Waiting for transaction consistency  (sorter_transaction.c:322)
…
xxxx-xx-xxT00:10:00 [SORTER          ]W:  Transaction consistency timeout occurred. 6 transactions are still open  (sorter_transaction.c:3575)

SQL Server ソースからの移行時における AWS DMS のオープントランザクション処理について

SQL Server を移行元として使用する場合も同様に、フルロード + CDC タスクの開始時にオープントランザクションが存在すると、AWS DMS の SOURCE_CAPTURE は以下のようなログを出力して検知します。

[SOURCE_CAPTURE  ]I:  do_get_best_lowset_position_for_highest_lsn_lookup(...) There is an outstanding active transaction!! It's oldest LSN is - '00000140:000217da:0001' It may be used as a '2nd chance'  SELECT MAX() candidate.  (sqlserver_log_queries.c:750)

SQL Server のデフォルトの分離レベルである READ COMMITTED で、READ_COMMITTED_SNAPSHOTOFF の場合、他のトランザクションによって変更されたがまだコミットされていないデータの読み取りは許可されません。
そのため、フルロード + CDC タスクで移行中のテーブルにオープントランザクションが存在する場合、そのテーブルに対する select * は、タスクの対象範囲内のアクティブなトランザクションがコミットまたはロールバックされるまでブロックされます。タスクの対象範囲外のテーブルにオープントランザクションが存在する場合、AWS DMS は一定時間待機した後にタスクを開始します。この場合、AWS DMS はフルロード + CDC タスクの開始のためにコミットやロールバックを待つことはなく、タスクの実行にも影響はありません。

この動作の結果、データの損失は発生しません。ただし、タスク対象範囲内のテーブルに関連するオープントランザクションがコミットまたはロールバックされるまで、フルロード + CDCタスクは Before load 状態のままとなります。

PostgreSQL ソースからの移行時における AWS DMS のオープントランザクション処理について

PostgreSQL を移行元とする場合、AWS DMS は PostgreSQL プラグイン pglogical または test_decoding を使用して SOURCE_CAPTURE コンポーネントを介して Write-Ahead Log (WAL) を読み取ります。
ただし、アクティブなトランザクションが存在する場合、レプリケーションスロットの作成処理 select * from pg_create_logical_replication_slot('slot_test','test_decoding'); は停止してしまいます。その結果、AWS DMS は変更を取得するためのレプリケーションスロットを作成できなくなり、ステートメントがタイムアウトするまで TransactionConsistencyTimeout の時間だけ待機します。
オープントランザクションが TransactionConsistencyTimeout の制限時間内にコミットまたはロールバックされれば、フルロード + CDC タスクは正常に開始され、データの損失も発生しません。しかし、オープントランザクションの実行時間が TransactionConsistencyTimeout を超えた場合、CDC の前提条件チェックが失敗し、以下のようなログが出力されます。

[SOURCE_CAPTURE ]E: RetCode: SQL_ERROR SqlState: 42P01 NativeError: 1 Message: ERROR: relation "pglogical.replication_set" does not exist; No query has been executed with that handle [1022502] (ar_odbc_stmt.c:3752)

[SOURCE_CAPTURE ]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:2581)

[SOURCE_CAPTURE ]E: Could not find any supported plugins available on source (postgres_plugin.c:269)

MySQL ソースからの移行時における AWS DMS のオープントランザクション処理について

MySQL を移行元とする場合、AWS DMS は変更の取得に binlog を使用します。MySQL の binlog にはコミットされていないトランザクションは含まれません。そのため、フルロード + CDC タスクの開始時に、AWS DMS はコミットされたトランザクションのみを参照できます。オープントランザクションは、コミットされるタイミング(フルロード中かフルロード後か)に応じて、キャッシュされた変更または CDC 変更として扱われます。このため、MySQL を移行元として使用する場合、フルロード + CDC タスクにおいてトランザクションの整合性タイムアウトの問題は発生しません。

ベストプラクティス

オープントランザクションを扱うためのベストプラクティスは以下の通りです。

  • データ移行の評価作業として、移行元データベースの長時間実行トランザクションを事前に十分確認し、アプリケーションやサービスの管理者と協力して、少なくとも移行フェーズの間はデータベース内の長時間トランザクションを最小限に抑えるためのプロセスを確立してください。
  • Oracleを移行元とする場合、トランザクションの整合性タイムアウトエラーが発生するとデータが失われる可能性があります。そのため、FailOnTransactionConsistencyBreached を true に設定し、早期にタスクを停止させる方がよいでしょう。
  • フルロード + CDC タスクは、移行元データベースの負荷が低い時間帯に開始してください。また、フルロード + CDCタスクを開始する前に、移行元データベースで予定されているダンプ処理や 抽出・変換・読み込み(ETL)ジョブの完了を待つことを推奨します。これにより、トランザクションの整合性タイムアウト問題の発生可能性を抑制し、また、処理すべき変更データ量を減らすことで、より早く移行元データベースに追いつくことができます
  • フルロード + CDC タスクを開始後、Before load 状態が長時間続く場合は、移行元データベースでオープントランザクションが存在していないか確認することを推奨します。
    • Oracle の場合は、v$transaction を確認してください。Oracle スタンバイ(Active Data Guard または Amazon RDS リードレプリカ)データベースをソースとして使用する場合、ソースデータベースのプライマリデータベースでオープントランザクションの詳細を確認してください。
    • PostgreSQL の場合は、pg_stat_activity)と pg_prepared_xacts)を確認してください。
    • SQL Server の場合は、DBCC OPENTRAN または dm_tran_active_transactions を確認してください。
  • TransactionConsistencyTimeout はデフォルトで 10 分です。ソースデータベースに常に 10 分を超えるトランザクションがある場合は、TransactionConsistencyTimeout の値を増やしてください。TransactionConsistencyTimeout を増やすと、AWS DMS の待機時間が長くなるため、TransactionConsistencyTimeout に達する前に、開いているトランザクションがコミットまたはロールバックされる可能性があります。TransactionConsistencyTimeout を増やしても、この記事で説明されている整合性タイムアウト関連のエラーが原因で、ソースデータベースで長時間実行されているトランザクションや、タスク障害を回避するための解決策にはならないことに注意してください。AWS DMS がソースデータベースでトランザクションのコミットまたはロールバックを待っている間、タスクは進行しません。したがって、上記のベストプラクティスを適用することは依然として重要です。
  • データの欠落や整合性の問題を特定するために、AWS DMS データ検証を使用してください。

まとめ

データベース移行プロジェクトにおいて、データの損失は決して許容できません。この記事では、オープントランザクションとは何か、そして異なるデータベースエンジンでフルロード + CDC タスクを開始する際に、AWS DMS がどのようにオープントランザクションを処理するのかについて説明しました。また、オープントランザクションに関連する問題を回避するため、AWS DMS タスクの計画から実行に至るまでのベストプラクティスを紹介しました。


著者について

Wanchen Zhao は AWS のパートナーソリューションアーキテクトです。

Rishi Raj Srivastava は、アマゾンウェブサービスの AWS DMS チームに所属するデータベースエンジニアです。

Sudip Acharya は、インドのAWS ProServe チームのコンサルタントとして、社内外の Amazon カスタマーのデータベース最新化プロジェクトに関するガイダンスや技術支援を行い、お客様が AWS を使用する際のソリューションの価値向上を支援しています。特に、データベースや移行関連ツールの設計・実装を得意分野としています。

翻訳はクラウドサポートエンジニアの小池が担当しました。原文はこちらです。