こんにちは😸
カスタマーサクセス部の山本です。
前提として、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 マネジメントコンソールでは「変換と移行」という枠の中に、同種移行の機能があります。
弊社のエンジニアがやってみたブログを執筆しているので、良ければ参考にしてください。
PostgreSQL 間のレプリケーションを DMS で行う際にハマったこと
さて、PostgreSQL の用意している論理レプリケーションが推奨される中、DMS の移行タスクを使って、PostgreSQL 間のレプリケーションを行ってみました。 継続的レプリケーション(CDC )を行うタスクを作成し、お試し的にやってみたのですが、色々と上手くいかずハマったので、内容を記載してみます。
移行タスク作成画面:
以前に執筆したブログ記事に、移行タスクの作成手順は記載しています。
良ければ参考にしてください。
移行タスクでのレプリケーション時に発生したエラーの確認方法
エラーの確認方法1:データ検証
移行タスクの設定で、「データ検証」を有効にすると、「テーブル統計」のタブに各テーブルの検証結果が出ます。
「テーブル統計」のタブ:
Validated
は検証済み、No primary key
は主キーがないというエラーです。
他にも、Mismatched records
というエラーもありました。
No primary Key には2種類あるようです。
No primary/unique key found
:ソーステーブルに主キーがないもののようです。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
私の理解で詳細に書くと、以下になります。
- ソーステーブルからターゲットテーブルにデータを移行する際に、LOB や NCLOB 型の列は一旦 NULL として INSERT 文を実行し、移行する。
- INSERT で移行したターゲットテーブルに対して、ソーステーブルから LOB や NCLOB 型の列の値のみを入れるようなアップデート文を実行する。この際に、ソーステーブルのプライマリキーを使って、ターゲットテーブルのプライマリキーが一致する行を見つけ、アップデート文を実施している。
以上より、No eligible primary/unique key found
の原因は以下です。
- ターゲットテーブルへの INSERT 実行時には、プライマリキーの値が text 型であると NULL となる。
- プライマリキーは重複できないため、プライマリキーが 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 の試走をしてきました。
山を走るのは気持ちが良いです。東京の里山は気温も高く、雪もなく、この時期はサイコーでした。
また、仲間に引っ張ってもらえて、ありがたかったです。