PostgreSQL 間のレプリケーションを DMS で行う際にハマったこと

記事タイトルとURLをコピーする

こんにちは😸
カスタマーサクセス部の山本です。

前提として、PostgreSQL 間のレプリケーションは、 PostgreSQL が用意しているツールを使うのが推奨のようです。

DMS の AWS ドキュメントには以下の記載があります。

PostgreSQL 以外のデータベースエンジンから PostgreSQL データベースに移行する場合、 AWS DMS はほとんどの場合、最適な移行ツールです。ただし、PostgreSQL データベースから PostgreSQL データベースに移行する場合、PostgreSQL ツールはより効果的です。

参考:ソースとしての AWS DMS PostgreSQL データベースの使用 - AWS Database Migration Service

ドキュメントを読むと、DMS は異なるデータベース間のデータ移行が得意なようです。
一方、PostgreSQL 間の移行は、PostgreSQL のネイティブなツールを使うことを推奨しています。
ネイティブなツールとしては、ストリーミングレプリケーションではなく、論理レプリケーション機能が使用できるようです。

同じリージョンにある 2 つの Aurora PostgreSQL DB クラスター (PostgreSQL の論理レプリケーション機能を使用)。

2023 年 6 月にリリースされた DMS の同種移行機能を、PostgreSQL 間のレプリケーションに利用するのも良いかと思います。

2023 年 6 月にリリースされた DMS の同種移行の AWS ドキュメントには、以下の記載があります。
PostgreSQL の場合、PostgreSQL のネイティブなツールを使用して、レプリケーションをするようです。

同種データ移行では、次の機能が利用できます。 AWS DMS は、同種データ移行に必要な 内の AWS クラウド コンピューティングリソースとストレージリソースを自動的に管理します。 は、データ移行を開始するときに、これらのリソースをサーバーレス環境に AWS DMS デプロイします。

  • AWS DMS は、ネイティブデータベースツールを使用して、同じタイプのデータベース間で完全に自動化された移行を開始します。
  • 同種データ移行を使用すると、データのみでなく、パーティション、関数、ストアドプロシージャなどのセカンダリオブジェクトも移行できます。
  • 同種データ移行は、フルロード、継続的なレプリケーション、継続的なレプリケーションを実行するフルロードの 3 種類の移行モードで実行できます。
  • 同種データ移行では、オンプレミス、Amazon EC2、Amazon RDS データベースをソースとして使用できます。同種データ移行では、移行ターゲットとして Amazon RDS または Amazon Aurora を選択できます。
  • 同種データ移行は、PostgreSQL、MongoDB、Amazon DocumentDB 移行のターゲットテーブル準備モードのみをサポートします。詳細については、「ターゲットテーブル作成モード」を参照してください。

AWS マネジメントコンソールでは「変換と移行」という枠の中に、同種移行の機能があります。

弊社のエンジニアがやってみたブログを執筆しているので、良ければ参考にしてください。

blog.serverworks.co.jp

blog.serverworks.co.jp

PostgreSQL 間のレプリケーションを DMS で行う際にハマったこと

さて、PostgreSQL の用意している論理レプリケーションが推奨される中、DMS の移行タスクを使って、PostgreSQL 間のレプリケーションを行ってみました。 継続的レプリケーション(CDC )を行うタスクを作成し、お試し的にやってみたのですが、色々と上手くいかずハマったので、内容を記載してみます。

移行タスク作成画面:

以前に執筆したブログ記事に、移行タスクの作成手順は記載しています。
良ければ参考にしてください。

blog.serverworks.co.jp

移行タスクでのレプリケーション時に発生したエラーの確認方法

エラーの確認方法1:データ検証

移行タスクの設定で、「データ検証」を有効にすると、「テーブル統計」のタブに各テーブルの検証結果が出ます。

「テーブル統計」のタブ:

Validated は検証済み、No primary keyは主キーがないというエラーです。
他にも、Mismatched records というエラーもありました。

No primary Key には2種類あるようです。

  1. No primary/unique key found:ソーステーブルに主キーがないもののようです。
  2. No eligible primary/unique key found:ソーステーブルに主キーがあるものの何かしらの問題があるもののようです。

エラーの確認方法2:例外テーブル awsdms_apply_exceptions

ターゲットとなるデータベースに awsdms_apply_exceptions テーブルがあります。
このテーブルには、ターゲットのテーブルに INSERT した際の例外を記録しています。

参考:制御テーブルタスク設定 - AWS Database Migration Service

select * from awsdms_apply_exceptions; で参照できます。

エラーNo primary/unique key found の原因

これは非常に単純で、テーブルに主キーの設定がありませんでした。
DMS では主キーがない場合、テーブルの移行に失敗します。

エラーNo eligible primary/unique key found の原因

適した主キーがない、ということですが、テーブル定義には主キーの設定がありました。

テーブル定義(\d+ table_name)から抜粋。

Column | Type | Collation | Nullable | Default
-----------------------+-----------------------------+-----------+----------+---------
integration_work_id | text | | not null |
〜割愛〜
Indexes:
"integration_work_pkey" PRIMARY KEY, btree (integration_work_id)

主キーである integration_work_id は text 型で、以下のような 値が入っています。

  • 11111111-2222-3333-aaaa-bbbbbbbbbbbb

ここでポイントになるのは、text 型という部分です。
text 型は文字列型の中でも、文字数の制限が無い、可変長の文字列になります。

参考:5.3. 文字列データ型

DMS の 継続的レプリケーション(CDC )を行うタスクでは、text 型を NCLOB 型として扱います。

つまりラージオブジェクトとして扱う、ということのようです。

参考:ソースとしての AWS DMS PostgreSQL データベースの使用 - AWS Database Migration Service

ドキュメントを読むと、ラージオブジェクトを移行する際には、単純に移行するのではなく、2段階の移行をするようです。

参考:AWS Database Migration Service のベストプラクティス - AWS Database Migration Service

私の理解で詳細に書くと、以下になります。

  1. ソーステーブルからターゲットテーブルにデータを移行する際に、LOB や NCLOB 型の列は一旦 NULL として INSERT 文を実行し、移行する。
  2. INSERT で移行したターゲットテーブルに対して、ソーステーブルから LOB や NCLOB 型の列の値のみを入れるようなアップデート文を実行する。この際に、ソーステーブルのプライマリキーを使って、ターゲットテーブルのプライマリキーが一致する行を見つけ、アップデート文を実施している。

以上より、No eligible primary/unique key found の原因は以下です。

  1. ターゲットテーブルへの INSERT 実行時には、プライマリキーの値が text 型であると NULL となる
  2. プライマリキーは重複できないため、プライマリキーが NULL の行が複数あることで、 INSERT に失敗する

例外テーブル awsdms_apply_exceptions に記録されたエラーは以下のようなものでした。

| Error while executing the query
test-replication | integration | integration_work | 2025-02-19 19:01:43.534219 | INSERT INTO "integration"."integration_work" (
"integration_work_id","integration_content","integration_date_time","integrater","integrater_time","updater","update_time" ) VALUES ('',
'','2025-02-19 09:01:37.779288','','2025-02-19 09:01:37.779288','','2025-02-19 09:01:37.779288')
| RetCode: SQL_ERROR SqlState: 23505 NativeError: 1 Message: ERROR: duplicate key value violates unique constraint "integration_work_pkey
"; +
| | | |
| Error while executing the query
test-replication | integration | integration_work | 2025-02-19 09:02:30.795294 | INSERT INTO "integration"."integration_work" (
"integration_work_id","integration_content","integration_date_time","integrater","integrater_time","updater","update_time" ) VALUES ('',
'','2025-02-19 09:02:24.305930','','2025-02-19 09:02:24.305930','','2025-02-19 09:02:24.305930')
| RetCode: SQL_ERROR SqlState: 23505 NativeError: 1 Message: ERROR: duplicate key value violates unique constraint "integration_work_pkey
"; +
| | | |

確かに INSERT しようとしている VALUES 内の一番最初の列にある integration_work_id は空文字列 ('') になっています。

VALUES ('','','2025-02-19 09:01:37.779288','','2025-02-19 09:01:37.779288','','2025-02-19 09:01:37.779288')

エラーメッセージは、キー値が重複していて一意になっていない、一意性制約違反というエラーと出力していました。

回避策1:制限付き LOB モード

完全 LOB モード で移行タスクを動かしていたところを、制限付き LOB モードにすると、2段階の処理ではなくなるようです。

制限付きLOBモードでは、 DMSが受け入れる最大LOBサイズを設定します。これにより、 DMSはメモリを事前に割り当て、LOBデータを一括でロードできます。

参考:AWS DMS タスクでのソースデータベースLOBのサポートの設定

回避策2:プライマリキーの型を変更する

今回の例であれば、プライマリキーintegration_work_idの値は 、11111111-2222-3333-aaaa-bbbbbbbbbbbb のような短い文字列です。
character varying(n)や、 varchar(n) といった型に変更しても良いかもしれません。

まとめ

DMS の移行タスクを使ってみて、ハマった 点を解説しました。
余談としては、「移行」に特化した機能なので、プライマリキー以外のインデックスは移行してくれなかったり、テーブルの Description も移行されていませんでした。 DMS は異なるデータベース間のデータ移行が得意なようです。また機会があれば、試してみたいです。
PostgreSQL 間のレプリケーションは、PostgreSQL のネイティブツールや、DMSの「同種移行」機能を利用するのが良さそうです。

弊社ではインサイトテクノロジー様と協業もしているので、データベースのプロを頼るのも手段かなと思いました。
サーバーワークスとインサイトテクノロジーが協業し、金融機関に特化したデータベースのクラウド化支援・運用に関する6サービスを提供開始 - 株式会社インサイトテクノロジー

お礼

また今回、私のドキュメントやログの読解のみでは調査が難航し、AWS サポートの方にかなりお力添えをいただきました。的確な原因分析とスピード感のあるご案内に感謝します。

余談

週末に、ハセツネ30 の試走をしてきました。
山を走るのは気持ちが良いです。東京の里山は気温も高く、雪もなく、この時期はサイコーでした。
また、仲間に引っ張ってもらえて、ありがたかったです。

山本 哲也 (記事一覧)

カスタマーサクセス部のインフラエンジニア。

山を走るのが趣味です。