DMS Schema Conversion の新機能「AWS MCP サーバーを利用した AI エージェントの自動化」を試してみた
はじめに
AWS DMS Schema Conversion には、ルールベースの変換エンジンに加えて生成AIによる追加変換機能があります。さらに、Kiro CLI と AWS MCP Server を組み合わせることで、DMS の操作自体を自然言語で自動化できます。
本記事では、Oracle独自構文を含むスキーマを対象に「ルールベース変換」「生成AI変換」「Kiroによるコード生成フォロー」の3段階でどこまでPostgreSQLに移植できるかを検証しました。
| 層 | 役割 |
|---|---|
| AWS MCP Server + Kiro | DMS API のオーケストレーション(プロジェクト作成、変換実行、レポート生成を自然言語で操作) |
| DMS Schema Conversion ルールベースエンジン | 通常のスキーマ変換(テーブル、インデックス、PL/SQL の構文変換) |
| DMS Schema Conversion 生成AI | ルールベースで「変換不可」と判定されたアクション項目に対する追加変換 |
| Kiro 単体のコード生成 | 上記3層で残ったアクション項目に対する補助的なコード生成 |
検証内容
検証環境
| リソース | スペック |
|---|---|
| ソース DB | RDS Oracle SE2 19c(db.m5.large, us-west-2) |
| ターゲット DB(DMS) | Virtual Aurora PostgreSQL 15 |
| ターゲット DB(構文検証) | EC2 上 PostgreSQL 16(Amazon Linux 2023) |
| DMS 変換設定 | MaterializedViewConvert=TABLE, ターゲットエンジンバージョン15 |
| Kiro CLI | AWS MCP Server(OAuth)経由で DMS API を操作 |
Oracle SE2 では Partitioning(PARTITION BY)と VPD(DBMS_RLS)が利用できないため、これらは検証対象外としています。SE2 で利用可能な COMPOUND TRIGGER、DBMS_SCHEDULER、SDO_GEOMETRY、マテリアライズドビュー等を検証対象に含めました。
Oracle スキーマの構成
検証用に MIGRATION_TEST スキーマを作成し、以下のオブジェクトを投入しました。
| オブジェクト | 種別 | Oracle 独自要素 |
|---|---|---|
| audit_log | TABLE | — |
| orders | TABLE | — |
| products | TABLE | SDO_GEOMETRY, XMLTYPE, CLOB, BLOB, TIMESTAMP WITH LOCAL TIME ZONE |
| mv_monthly_sales | MATERIALIZED VIEW | FAST REFRESH ON COMMIT |
| pkg_order_mgmt | PACKAGE | DBMS_SCHEDULER, DBMS_LOB, UTL_FILE, CONNECT BY LEVEL, SYS_REFCURSOR |
| pkg_notification | PACKAGE | — |
| trg_orders_audit | TRIGGER | COMPOUND TRIGGER(AFTER EACH ROW + AFTER STATEMENT) |
全25オブジェクト(テーブル5、パッケージ2+ボディ2、MV1、トリガー1、インデックス6、LOB5、シーケンス3)が VALID であることを確認した上で変換を実行しています。
オブジェクト別変換結果
DMS Schema Conversionでルールベース変換と生成AI変換をそれぞれ実行しました。EnableGenAiConversionをfalse/trueに切り替え、S3にエクスポートしたSQLを比較した結果が以下です。
- DMS 直接適用: 成功 8/13、失敗 5/13(COMPOUND TRIGGERはDMS出力なしのため対象外、うち1件は連鎖失敗)
- Kiro フォロー適用: 構文適用成功 14/14(1イテレーション)
| オブジェクト | DMS 変換結果 | 生成AI 差分 | PG 直接適用 | Kiro フォロー |
|---|---|---|---|---|
| audit_log (TABLE) | ✅ 成功 | なし | ✅ 成功 | — |
| orders (TABLE) | ✅ 成功 | なし | ✅ 成功 | — |
| products (TABLE) | ✅ 成功 | なし | ❌ geometry型なし |
PostGIS で解決 |
| mv_monthly_sales (TABLE) | ✅ 成功 | なし | ✅ 成功 | — |
| idx_orders_date (INDEX) | ✅ 成功 | なし | ✅ 成功 | — |
| i_snap$_mv_monthly_sales (INDEX) | ✅ 成功 | なし | ❌ sys_op_map_nonnull |
業務用INDEXに変更 |
| PK 制約 ×3 | ✅ 成功 | なし | ✅ 成功(2/3) | — |
| pkg_notification$send (PROC) | ✅ 成功 | なし | ✅ 成功 | — |
| pkg_order_mgmt$place_order (PROC) | ⚠️ 部分変換 | あり | ✅ 成功 | pg_cron で再実装 |
| pkg_order_mgmt$archive_old_orders (PROC) | ✅ 成功 | なし | ❌ aws_oracle_extなし |
テーブル出力+COPY |
| pkg_order_mgmt$get_order_summary (FUNC) | ✅ 成功 | なし | ❌ aws_oracle_dataなし |
generate_series で再実装 |
| trg_orders_audit (TRIGGER) | ❌ COMPOUND TRIGGER非対応 | — | — | 行トリガーに変換 |
※ DMS直接適用の13件は、テーブル4(audit_log、orders、products、mv_monthly_sales)+ INDEX2 + PK制約3 + PROC/FUNC4です(DMS出力の論理オブジェクト単位)。COMPOUND TRIGGERは非対応のため直接適用の対象外です。Kiroフォローの14件は、DMS出力にKiroで追加・修正したオブジェクト(archive_exportテーブル、トリガー関数等)を合わせた適用単位です。
生成AI変換で差分が出た箇所(本検証スキーマの場合)
ルールベースと生成AIで出力が異なったのは pkg_order_mgmt$place_order 内の DBMS_SCHEDULER.CREATE_JOB 呼び出し部分のみでした。
ルールベース変換の出力:
/*
[5501 - Severity CRITICAL - PostgreSQL doesn't support functionality similar to the
SYS.DBMS_SCHEDULER.CREATE_JOB(...) module.
Revise your converted code to use AWS Lambda with scheduled events.]
DBMS_SCHEDULER.CREATE_JOB(
job_name => v_job_name,
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN migration_test.pkg_notification.send(' || p_order_id || '); END;',
start_date => SYSTIMESTAMP + INTERVAL '5' MINUTE,
enabled => TRUE
)
*/
ルールベースは該当コードを コメントアウト し、アクション項目 5501(CRITICAL)として「AWS Lambda with scheduled events で書き換えよ」と提案しています。
生成AI変換の出力:
/* [5444 - Severity LOW - This conversion uses machine learning models that generate
predictions based on patterns in data. Machine learning output is probabilistic and
should be reviewed for accuracy, including human evaluation, as needed for your use case.] */
/* vvv ---- Beginning of statement generated using GenAI. ---- vvv */
CALL DBMS_SCHEDULER.CREATE_JOB(
job_name => v_job_name,
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN migration_test.pkg_notification.send(' || p_order_id || '); END;',
start_date => aws_oracle_ext.systimestamp() + '5 MINUTE'::INTERVAL,
enabled => TRUE
);
/* ^^^ ---- End of statement generated using GenAI. ---- ^^^ */
生成AIは コメントアウトせず構文変換を施したコード を生成しています。ただしPostgreSQLにDBMS_SCHEDULERパッケージが存在しないため、このコードをそのまま実行できません。元の5501(CRITICAL)は5444(LOW)に置き換わりましたが、これは生成AIによる出力であること、および人間によるレビューが必要であることを示すアクション項目です。
| 比較観点 | ルールベース | 生成AI |
|---|---|---|
| 出力形式 | コメントアウト(実行不可) | CALL文(構文変換済み、未解決の依存あり) |
| 重大度 | CRITICAL (5501) | LOW (5444) |
| SYSTIMESTAMP | Oracle構文のまま | aws_oracle_ext.systimestamp() |
| INTERVAL 表現 | INTERVAL '5' MINUTE |
'5 MINUTE'::INTERVAL |
| 実用性 | 手動書き換え必須 | そのままでは動作しない |
本検証の範囲では、生成AIによる差分はルールベースで変換不可と判定されたDBMS_SCHEDULER.CREATE_JOB部分に限られ、他のオブジェクトの出力差分は確認されませんでした。
アセスメントレポートのアクション項目
生成AI変換有効時のアセスメントレポートには以下のアクション項目が残りました。
| アクション項目 | 重大度 | 内容 | 対応方法 |
|---|---|---|---|
| 5242 | — | COMPOUND TRIGGER 非対応 | 行トリガーに分割 |
| 5444 | LOW | 生成AI変換結果(要レビュー) | 人間によるレビュー |
| 5584 | — | タイムゾーン設定の確認 | 手動確認 |
| 5798 | — | DBMS_LOB の一時LOB動作差異 | ロジック確認 |
| 9994 | — | 変換不可(UTL_FILE) | 手動変換 |
DMS 変換結果を PostgreSQL に直接適用
DMSのルールベース変換が出力したSQLをEC2上のPostgreSQL 16に直接実行したところ、13件中8件が成功しました。DMS Schema Conversionのターゲットバージョンは Aurora PostgreSQL 15 で実行しており、以下は PostgreSQL 16 での構文検証結果です。
成功(8件): audit_log, orders, mv_monthly_salesのテーブル作成、idx_orders_date、PK制約2件、pkg_notification$send、place_order(DBMS_SCHEDULER部分はコメントアウト状態のため構文エラーなし。フル機能再現は後述のKiroフォローで対応)
失敗(5件):
| オブジェクト | エラー |
|---|---|
| products (TABLE) | type "geometry" does not exist — PostGIS 未導入 |
| i_snap$_mv_monthly_sales (INDEX) | column "sys_op_map_nonnull" does not exist — Oracle 内部関数 |
| PK: products | products テーブル未作成のため連鎖失敗 |
| get_order_summary (FUNCTION) | schema "aws_oracle_data" does not exist — aws_oracle_dataスキーマ依存 |
| archive_old_orders (PROCEDURE) | schema "aws_oracle_ext" does not exist — aws_oracle_extスキーマ依存 |
今回のDMS変換結果の一部には、aws_oracle_extおよびaws_oracle_dataスキーマを参照するSQLが含まれていました。素のPostgreSQLではこれらのスキーマが存在せず、DBMS_LOBやUTL_FILEのラッパー呼び出しがエラーになります。
変換不可部分の Kiro フォロー
DMS で変換できなかった部分、およびaws_oracle_ext / aws_oracle_dataスキーマ依存で素の PostgreSQL では動作しない部分を Kiro に生成依頼しました。
DBMS_SCHEDULER → pg_cron(自己削除パターン)
Oracle のDBMS_SCHEDULER.CREATE_JOBは1回限りの遅延ジョブ(5分後に実行)を作成しています。pg_cronはcron式ベースの定期実行が基本のため、「毎分チェック → 指定時刻以降の最初の実行契機で処理 → 自己削除」のパターンで再現しました。このためOracleの厳密な5分後とは異なり、最大約1分の遅延が生じ得ます。
CREATE OR REPLACE PROCEDURE migration_test.pkg_order_mgmt$place_order(
IN p_customer_id DOUBLE PRECISION,
IN p_total DOUBLE PRECISION,
OUT p_order_id DOUBLE PRECISION
)
LANGUAGE plpgsql
AS $$
DECLARE
v_job_name TEXT;
v_fire_at TIMESTAMP;
BEGIN
INSERT INTO migration_test.orders (customer_id, order_date, total_amount)
VALUES (p_customer_id, CURRENT_TIMESTAMP::TIMESTAMP(0), p_total)
RETURNING order_id INTO p_order_id;
v_job_name := 'notify_' || p_order_id::BIGINT;
v_fire_at := CURRENT_TIMESTAMP + INTERVAL '5 minutes';
PERFORM cron.schedule(
v_job_name,
'* * * * *',
format(
'DO $j$ BEGIN IF CURRENT_TIMESTAMP >= %L::TIMESTAMP THEN '
|| 'CALL migration_test.pkg_notification$send(%s); '
|| 'PERFORM cron.unschedule(%L); END IF; END $j$;',
v_fire_at,
p_order_id,
v_job_name
)
);
END;
$$;
DBMS_LOB + UTL_FILE → テーブル出力 + COPY
OracleのDBMS_LOB.CREATETEMPORARY / WRITEAPPENDによるCSV文字列組み立てとUTL_FILEによるファイル出力は、PostgreSQLではINSERT ... SELECTでテーブルに書き出し、外部からCOPY TOでCSV化する方式に置き換えました。Aurora PostgreSQLではホストファイルシステムへの直接書き込みができないため、Aurora環境との共通実装としています。
-- UTL_FILE 代替のアーカイブ出力先テーブル
CREATE TABLE migration_test.archive_export(
order_id BIGINT,
total_amount DOUBLE PRECISION,
archived_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE OR REPLACE PROCEDURE migration_test.pkg_order_mgmt$archive_old_orders(
IN p_before_date TIMESTAMP WITHOUT TIME ZONE
)
LANGUAGE plpgsql
AS $$
BEGIN
INSERT INTO migration_test.archive_export (order_id, total_amount)
SELECT order_id, total_amount
FROM migration_test.orders
WHERE order_date < p_before_date;
DELETE FROM migration_test.orders
WHERE order_date < p_before_date;
END;
$$;
CONNECT BY LEVEL → generate_series
DMSはCONNECT BY LEVELをWITH RECURSIVEに変換しました。ただしaws_oracle_ext.ADD_MONTHSとaws_oracle_data.TCursorAttributesに依存する形です。KiroではPostgreSQLネイティブのgenerate_series + INTERVAL演算で再実装しました。
CREATE OR REPLACE FUNCTION migration_test.pkg_order_mgmt$get_order_summary(
IN p_customer_id DOUBLE PRECISION
)
RETURNS REFCURSOR
LANGUAGE plpgsql
AS $$
DECLARE
v_cursor REFCURSOR;
BEGIN
OPEN v_cursor FOR
SELECT
gs AS month_offset,
date_trunc('month', CURRENT_DATE) - (gs - 1) * INTERVAL '1 month' AS target_month
FROM generate_series(1, 12) AS gs;
RETURN v_cursor;
END;
$$;
本コードはgenerate_seriesによる月次系列生成の骨格のみで、p_customer_idを用いた顧客別集計ロジックは含まれていません(構文変換の確認が目的です)。
COMPOUND TRIGGER → 行トリガー
OracleのCOMPOUND TRIGGERはAFTER EACH ROWで変更行を配列に蓄積し、AFTER STATEMENTで一括INSERTする構造です。DMS Schema ConversionではCOMPOUND TRIGGERが非対応(アクション項目5242)のため未変換となり、PostgreSQLの行トリガーで再実装しました。
CREATE OR REPLACE FUNCTION migration_test.trg_orders_audit_fn()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
IF TG_OP = 'DELETE' THEN
INSERT INTO migration_test.audit_log (operation, order_id, event_ts)
VALUES ('DELETE', OLD.order_id, CURRENT_TIMESTAMP);
RETURN OLD;
ELSE
INSERT INTO migration_test.audit_log (operation, order_id, event_ts)
VALUES (TG_OP, NEW.order_id, CURRENT_TIMESTAMP);
RETURN NEW;
END IF;
END;
$$;
CREATE TRIGGER trg_orders_audit
AFTER INSERT OR UPDATE OR DELETE ON migration_test.orders
FOR EACH ROW
EXECUTE FUNCTION migration_test.trg_orders_audit_fn();
Kiro フォロー適用結果
上記のコードを含む全14オブジェクトをEC2上のPostgreSQL 16に適用し、14/14で構文適用に成功しました(1イテレーション)。ここでの「成功」はPostgreSQL 16へのCREATEが通ったことを指し、Oracle元コードとの機能同等性を保証するものではありません。機能テストとしてordersテーブルへのINSERT → トリガー発火 → audit_log記録を確認しています。pg_cronによる5分後の実発火は本検証では確認していません。
Kiro + AWS MCP Server での操作
Kiro CLI に AWS MCP Server を接続し、DMS Schema Conversion の操作を自然言語で実行しました。以下は代表的な操作フローです。
入力プロンプト例:
Convert the MIGRATION_TEST schema to Aurora PostgreSQL using rule-based conversion only (GenAI disabled). The migration project is oracle-to-pg-schema-conversion in us-west-2. Export the converted SQL scripts to S3.
このプロンプトに対し、Kiro は以下の API を順に呼び出しました。
describe-conversion-configuration— 現行設定の確認modify-conversion-configuration—EnableGenAiConversion=falseに変更start-metadata-model-conversion— 変換実行wait metadata-model-converted— 完了待機start-metadata-model-export-as-script— S3エクスポートwait metadata-model-exported-as-script— エクスポート完了待機describe-metadata-model-exports-as-script— S3キー確認
全4プロンプト(スキーマ確認 → ルールベース変換 → 生成AI変換 → アセスメント生成)で合計19回の API 呼び出しを実行しました。
途中、waiterのfilter名に誤ったパラメータ(schema-conversion-operation-id)を使用しInvalidParameterValueExceptionが発生しました。Kiroはエラーメッセージから正しいfilter名(request-id)を推定して自己修復しています。以降同種のエラーは再発していません。
MCP はAPI呼び出しの自動化レイヤーであり、変換エンジン自体は同じです。本検証では、同一の変換設定・入力スキーマで実行した範囲において、MCP経由と手動操作で変換結果に差分は確認されませんでした。
まとめ
今回の検証では、DMS Schema Conversion のルールベース変換と生成AI変換を使って、Oracle 独自構文を含むスキーマを PostgreSQL 向けに変換しました。DMS + 生成AIによる変換後に残った主な課題は、拡張の追加が必要なもの(PostGIS、pg_cron)、設計変更が必要なもの(UTL_FILE → テーブル出力 + COPY)、性能特性を単純には再現できないもの(COMPOUND TRIGGER のバルク処理)に分かれました。
Kiro フォローでは、DMS変換結果に Kiro で生成・補正したコードを加えた全14適用単位を、1イテレーションで PostgreSQL 16 の構文検証に通過させることができました。ただし、ここでの成功は CREATE 文が通ったことを指しており、Oracle 元コードとの機能同等性や性能特性まで保証するものではありません。実際の設計判断や機能検証は、人間が担う領域として残ります。
本検証で生成AI変換の差分が確認できたのは、DBMS_SCHEDULER.CREATE_JOB の1箇所のみでした。これは、本検証スキーマが COMPOUND TRIGGER や INDEX など、生成AI変換の対象外とされる要素を多く含んでいたことが一因と考えられます。対象要素の多いスキーマでは、生成AIが介入する箇所が増える可能性があります。
生成AIが介入した箇所では、ルールベース変換のようにコメントアウトで残すのではなく、PostgreSQL向けの構文変換を試みたコードが出力されました。一方で、出力された CALL DBMS_SCHEDULER.CREATE_JOB(...) はそのまま PostgreSQL で動作するものではなく、5444 のアクション項目が示す通り、人間によるレビューと再設計が必要です。
Kiro + AWS MCP Server によるオーケストレーションは、同じ設定で DMS Schema Conversion を実行する限り、変換エンジンそのものを変更するものではありません。本検証では、19回のAPI呼び出しを自然言語4プロンプトで完了でき、途中のAPIパラメータ誤りも自己修復されたため、DMS操作の効率化という点で有効性を確認できました。
参考リンク











