ForgeVision Engineer Blog

フォージビジョン エンジニア ブログ

AWS DMS × PostgreSQL でカラムが更新されない?実際にハマった原因と解決法

こんにちは、AWS グループのナガトモです 🙋‍♀️

AWS DMS を使って RDS(PostgreSQL)間のレプリケーションを試したところ、いろいろトラブった結果、最終的に 「あれ、カラムが更新されない…?🤔」っていう謎バグ(?)に遭遇しまして。

備忘録として、構成・実施内容・ハマりポイント・解決法まで、リアルな検証ログをもとにまとめておきます。
「DMS 検証中に謎のトラブルで詰まってる方」のヒントになれば幸いです!

💡 検証ポイントまとめ(備忘録)

  • VPC Peering は両側から確認&アクセプトを!
  • DMS レプリケーションは rds_superuserrds_replication ロールが必須
  • CDC を使う場合は、開始ポイントとカラム定義に注意
  • ソース・ターゲットのスキーマ整合性も事前にチェック

前提

まずは、この構成図をご覧ください。

  • RDS(PostgreSQL 17.2)を自分と先輩のVPCにそれぞれ立てる
  • データ挿入と確認用に、EC2(Amazon Linux 2023)も配置

ダークテーマの構成図にしたら、私の黒ネコアイコンが溶け込んで見えなくなったのは小ネタ

検証内容

DMS を使って、先輩の VPC に立てた RDS から私の VPC に立てた RDS にデータをレプリケーションします。

🧙‍♂️ イリュージョン的データ移動、スタート。

VPC Peering

DMS を使うため、先輩の VPC とピアリングしました。
そして、勝手にアクセプトしました。

ちなみに VPC Peering の料金体系、最近シンプルになってわかりやすくなってます👇

aws.amazon.com

DMS エンドポイント

DMS で大切なのがエンドポイント設定。

  • ソース:先輩の RDS
  • ターゲット:自分の RDS

イメージは下図のような形です。
自分の VPC に DMS を構築 → 先輩 VPC の DB からデータ引っこ抜くイメージです。

ソース、ターゲット共に、別々でテストができるのがなかなか良きでした。

ここでの注意点 👉

rds_superuser と rds_replication ロールが必要です!!
地味にハマりました。公式ドキュメントも貼っときます。

docs.aws.amazon.com

DMS インスタンス

レプリケーションインスタンスは、一番安価な dms.t3.medium にしました。
エンジンバージョンは、3.5.4 です。

本番相当の検証をしたくて インスタンスを起動しましたが、レプリケーションにラグを感じることがなかったので、サーバーレスでも良かったです。

データベース移行タスク

続いて、移行タスクを作りました。
ログは有効にせず、 フルロードと継続的なレプリケーションを選択肢して、タスクを実行したところ、ロード完了になりました。

スクリーンショットが分かりづらいのですが、ここがハマりポイントでした。

カラムが更新されずハマる

最後に、ハマったポイントを書いて終わりたいと思います。

まず、先輩の VPC に立てた RDS にデータを突っ込みました。
以下のような感じです。

値に意味はありません。本当です!!

otadb=> insert into nagatable (id, name, lifeexp) values (7, 'otani', 100);
INSERT 0 1
otadb=>
otadb=> select * from nagatable;
id | name | lifeexp
------+--------+-----
1 | yamaguchi | 1280
2 | kurihara | 1020
3 | matsuo | 980
4 | fujihara | 550
5 | nagatomo | 12420
6 | suzuki | 720
7 | otani | 100
(7 rows)

レプリケーション先で値を確認すると、以下のようになりました。

postgres=> select * from sampletable;
id | exp
------+--------+-----
1 | 1280
2 | 1020
3 | 980
4 | 550
5 | 12420
6 | 720
7 | 100
(7 rows)

name カラムがレプリケーションされていません。
先輩テーブルにデータを追加するも改善されず、私の方のテーブルを削除してから、先輩のテーブルのデータを更新しても改善されず。
タスクを作り直しても改善しませんでした。

どうやって解決したか?

最終的に、移行タイプをフルロードに変更して解決しました。
が、原因が謎のままだと夢に出てきちゃう!との思いから色々調べたところ考えられる原因は以下のようなものがあるみたいです💭
CDC中のスキーマ不一致(タイミングの問題) ←今回のはたぶんこれ!!
・ フルロード中やCDC準備中に、スキーマが変更された(列の追加/削除/型変更など)
 →DMSは初期スキーマをキャッシュして使うので、変更後のカラムを認識できない
 →その結果、「欠損したカラム」が出る  
DMSのターゲットデータ型マッピングの失敗
タスク設定の「ターゲットテーブル準備モード」設定ミス
フルロード+CDCのときに【既存のテーブルをそのまま使う】設定になっていると、ターゲットに既存の不完全なテーブルが残ってる状態でCDCだけ走り、カラム不足が継続することも🤔

要件に合わせて検証をしたのですが 開始ポイントとカラム定義には注意が必要 と感じました。
今回わたしはフルロードだと欠損なく成功したー!わーい🙌 で検証終わりましたがどうしてもCDCも実行したい場合は、一度 ターゲットテーブルを全削除してからDMSタスクを「フルロードのみ」で再実行して別タスクを追加する形でCDCを有効化すれば事象の切り分けもできていいかもしれませんね🧐

docs.aws.amazon.com

以上です。

この記事が「同じところでハマっている誰か」の助けになりますように。
他にも DMS や RDS の検証で「ここ詰まった!」という方がいたら、ぜひコメントで教えてくださいね!

コメントできるのかしら...?