こんにちは。テクニカルサポート課の森本です。
ネットワーク編に引き続き、DMSのレプリケーションタスクで発生する問題のトラブルシューティング方法の概略を説明します。
レプリケーションタスクにおける細かなパラメータやデータベースエンジン毎の設定の内容ではなく、トラブルシュートの切り分けの観点を理解するためのエントリとなっています。
レプリケーションタスクの概要
フルロード(Full-load)
タスク開始時にソースデータベース側に存在する既存データをターゲットデータベースに移行します。 タスク開始後にソースデータベース上で行われた変更はターゲットデータベースに適用されません。 移行の最中、ソースデータベース上のワークロードの停止が可能な場合はこちらの移行で十分です。
CDC(Change Data Capture)
タスク開始後、ソースデータベース上で行われた変更を非同期でターゲットデータベースに適用します。 タスク開始時にソースデータベース上に存在する既存データの移行は行われません。 フルロード以外の方法(ネイティブなダンプ/リストアやCSVファイルのロードなど)により既存データの移行が完了しているものの、依然としてソースとターゲットのデータ同期を図りたい場合に有効です。
フルロード + CDC
上述のフルロードとCDCを合わせた機能です。 まずタスクの開始時、フルロードを開始するとともに、ソースデータベース上で行われた変更をキャッシュします。 フルロードが完了したのち、キャッシュされた変更をターゲットに適用します。 その後、ソースデータベース上で行われた変更を継続的にターゲットデータベースに適用します。 ダウンタイムを最小化してソースデータベースとターゲットデータベースの移行を行いたい場合に有効です。
レプリケーションタスクのコンポーネント
上述のフルロードやCDCを実現するために、レプリケーションタスクには図中のようなコンポーネントが存在します。ここでは主要なものを解説します。 どのコンポーネントがどの機能に対応するかを理解しておくと、後述のログ解析に役立ちます。
フルロード
Source Unload
ソースデータベースから既存データをフェッチします。 具体的には、タスクで指定したテーブルに SELECT クエリを発行して既存の全データを取得します。
Target Load
Source Unloadでフェッチしたデータをターゲットに適用します。 具体的には、取得したデータをCSVファイルに変換後に一括ロードや、メモリ上のデータを直接ロードなど効率の良い方法で適用します。(ターゲットのデータベースエンジン毎に異なります) 追加の設定によっては、INSERT文による適用に変更可能なデータベースエンジンもあります。
CDC
Source Capture
ソースデータベースで発生した変更を受信バッファにキャプチャします。 この際、ソース側で発行した変更ログ(MySQL なら binlog、PostgreSQL なら WAL) をレプリケーションインスタンスで読み取ります。
Sorter
Source Capture でキャプチャしたデータを COMMIT の順番にソートする、COMMIT済みのデータのみ 送信バッファに送るなどを行います。
Target Apply
送信バッファ内のデータをターゲットデータベースに適用します。 変更内容から DML (INSERT、UPDATE、DELETE)を生成、実行しますが、必ずしもソース側と同様のDMLが実行されるわけではありません。あくまでも DML の実行結果が同等になります。 例えばソース側で複数行に一括で適用した DML が、ターゲット側でプライマリキー毎に一行づつ適用されるなどの動作があります。
タスクログ
レプリケーションタスクにエラーが発生する場合、重要なのはタスクログの内容を確認することです。とても重要です。これがないとトラブルシュートが始まらないくらい重要です。
ロギングタスク設定を使用して、記録するコンポーネントアクティビティと、ログに書き込まれる情報量を指定できます。
ここでいうコンポーネントとは上述の Source Unload などのことであり、エラーが発生しているコンポーネントを特定することで、見直すべき設定にアタリをつけることができます。
なお、タスクログの出力設定を行なっても CloudWatch Logs にログ出力が行われない場合、IAM ロールの設定が行われていない可能性があります。
AWS DMS タスクに CloudWatch Logs が表示されない理由のトラブルシューティング | AWS re:Post
CloudWatch Logs がタスクに対して有効になっていても、ログを表示できない場合は、AWS の ID とアクセス管理 (IAM) ロールを確認します。dms-cloudwatch-logs-role がリストされていることを確認します。ロールがリストにない場合は、ロールを作成してください。
実際のエラーの例
いくつか、タスクログへの実際のエラー内容のエントリを紹介します。
[SOURCE_UNLOAD ]E: RetCode: SQL_ERROR SqlState: HYT00 NativeError: 0 Message: [Microsoft][ODBC Driver 17 for SQL Server]Query timeout expired
こちらは SOURCE_UNLOAD なので、フルロード時におけるソース側にエラーの原因がありそうです。フルロードの開始時においてソースデータベースの負荷が高かったため、ソースからデータの取得をおこなうSELECTクエリがタイムアウトしたという状況でした。ソースデータベースでの負荷が少ない時間に再度実行することで問題解決にいたりました。
[SOURCE_CAPTURE ]E: Error 'Access denied; you need (at least one of) the SUPER, REPLICATION CLIENT privilege(s) for this operation' reading binlog events
こちらは SOURCE_CAPTURE なので、CDC によるソース側にエラーの原因がありそうです。このケースではソースは MySQL だったのですが、ソースデータベースに接続しているユーザに変更ログ(binlog)の読み取りに必要な権限が不足していることが原因でした。そのため、ソースデータベース上で適切なユーザに権限を付与することにより問題解決にいたりました。
[TARGET_APPLY ]E: RetCode: SQL_ERROR SqlState: HYT00 NativeError: 0 Message: [Microsoft][ODBC Driver 17 for SQL Server]Query timeout expired
こちらは TARGET_APPLY なので、CDC によるターゲット側にエラーの原因がありそうです。このケースではクエリがタイムアウトしている様子が読み取れたので、ターゲット側でタイムアウト秒数を伸ばすことにより問題解決にいたりました。
[TARGET_APPLY ]E: Table 'public'.'awsdms_apply_exceptions' does not exist, insufficient privileges or no supported columns
こちらも TARGET_APPLY なので、CDC によるターゲット側にエラーの原因がありそうです。このケースでは、CDC の際に レプリケーションタスクによって作成されるはずのコントロールテーブルが見つからないというエラーでした。タスク設定にてコントロールスキーマを明示的に設定することにより、問題解決にいたりました。
DMS により発生するエラーは上述のものに限らず無数に発生し得ますが、問題がありそうなコンポーネントを特定し、都度 AWS ドキュメントと付き合わせて怪しい設定を確認する手順は大半のエラーに有効なものと思います。
まとめ
レプリケーションタスクにおけるコンポーネントと、タスクログを用いたトラブルシュートの概要について説明を行いました。
この記事が DMS のトラブルシュートに立ち向かうどなたかの参考になれば幸いです。