AWS Database Migration Serviceを使ったデータ移行手順まとめ(OracleからMySQL編)

2016.09.17

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

西澤です。前回、MySQLからAurora(または別環境のMySQL)へのデータ移行をDMSを使って行った手順をご紹介したのですが、今度はOracleからMySQLへのデータ移行をDMSを使って対応した内容をまとめておきたいと思います。試行錯誤も多かったので、行き当たった事象を全て細かく書いておきます。

DMSサービスの基本的な部分は共通する部分も多いですし、今回は省略するて説明や手順も多いので、前回の記事も事前に読んでおいていただけると理解がスムーズかと思います。

また、DMSって何?という方は、まず下記記事をご覧ください。

1. 事前準備

前回の記事にも書きましたが、データ移行作業においては事前準備と移行検証が最も重要です。ドキュメントに目を通して、前提条件に不足が無いか、制限事項は何なのか、しっかり確認しておきましょう。

ソースDB(Oracle)側の前提作業

ソースDBがオンプレ環境のOracleの場合の注意事項は、下記ページに詳しく書いてあります。

データソースがOracleの場合には、デフォルトではLogMinerが利用されます。

|方式|デフォルト|大雑把な説明| |---|---|---| |LogMiner|Default|負荷が高いが制限が少ない| |Binary Reader|connection parameter追加が必要 useLogMinerReader=Y|負荷は低いが制限が多い|

制限事項や接続するユーザに必要となる権限情報も詳しく書いてあります。しっかり確認しておきましょう。また、今回検証を行った際には、Full Loadのみで、change data capture (CDC)を利用しない場合でも、V$LOGMNR_LOGSへのアクセス権限を付与しておかないと下記のようにエラーとなる場合がありました。

No permissions to access V$LOGMNR_LOGS [120401] Endpoint initialization failed.

加えて、今回の移行では、SCT(Schema Conversion Tool)も利用することにしました(※詳細は後述)。その場合、下記エラーとなりSCTからの接続に失敗しました。

The specified account (xxxxxx) does not have sufficient privileges for working with the following object(s):
ORACLE Server : [SELECT ANY DICTIONARY]

SCT利用の場合には、下記ドキュメントの通り"SELECT ANY DICTIONARY"権限も必要となりますのでご注意ください。

十分な参照権限があるアカウントを用意した上で、下記設定が有効となっていることも確認しておきましょう。

  • ARCHIVELOGモード
  • Supplemental Logging

ターゲットDB(MySQL)側の前提作業

ターゲットDBをMySQLの5.7で用意したところ、下記エラーが出てSCT(※詳細は後述)からの接続が失敗することがありました。

Cannot load objects tree.
java.sql.SQLException: The 'INFORMATION_SCHEMA.GLOBAL_VARIABLES' feature is disabled; see the documentation for 'show_compatibility_56'

メッセージに従って、DBパラメータグループから、"show_compatibility_56=1"を設定したところ、SCTより接続できました。公式ドキュメントには情報が見つからなかったので、バージョン依存の問題かもしれません。

2. スキーマ移行

前回からの繰り返しになりますが、重要なのでここはおさらいです。DMSではビューや制約等を全て移行してくれるわけではありません。基本的には、移行してくれるのはデータと主キーと考えても問題ありません。その為、テーブル定義等の情報は別の手段で移行する必要があります。

Schema Conversion Toolとは?

そこで、今回はSCT(Schema Conversion Tool)を利用して、スキーマ移行をすることにしました。

SCTはDMSによる移行を補助する為のツールとして公開されているクライアントソフトウェアです(AWS Management Consoleから操作するようなサービスではありません)。今回はソースDB、ターゲットDBの両方に接続可能なWindowsサーバ上にソフトウェアを導入して利用しました。

SCTは、OracleからMySQLへの移行に限らず、異なるDBエンジン間のスキーマ移行をサポートしてくれる強力なツールです。

Source Database Target Database
Microsoft SQL Server Amazon Aurora, MySQL, PostgreSQL
MySQL PostgreSQL
Oracle Amazon Aurora, MySQL, PostgreSQL
Oracle Data Warehouse Amazon Redshift
PostgreSQL Amazon Aurora, MySQL
Teradata Amazon Redshift

詳細は公式ドキュメントをぜひご覧ください。

SCTによるスキーマ移行用SQL作成

まずは、SCTを利用して移行レポートを作成してみましょう。SCTにより移行できないリソースがないか、それぞれの移行作業の難易度がどの程度か、を評価して表示してくれます。

今回はSCTを利用して生成したSQLを保存して編集して実行することで、スキーマ移行を実現することにしました。Apply to databaseを使っても良いのですが、実際には手動での修正作業が必要となる場合がほとんどではないかと思いますし、何が実行されているか目に見えないこともあるので、一旦SQLにして保存しておくことをお勧めします。

SCTから生成されたスキーマ移行用SQLサンプル

今回Oracleからのスキーマ移行用に生成されたSQLは以下のように構成されていました。こちらはあくまでサンプルなので、データソースの状態や抽出方法によって生成されるSQLも変化するはずですが、参考情報として記載しておきます。実際にはDDLの見直しもかかるケースが多いのですが、その叩き台を作ってもらえる、というだけでも助かるケースが多いのではないかと思います。

delimiter $$

-- ------------ Write DROP-DATABASE-stage scripts -----------
DROP DATABASE IF EXISTS DBHOGE;$$

-- ------------ Write CREATE-DATABASE-stage scripts -----------
CREATE DATABASE IF NOT EXISTS DBHOGE;$$

-- ------------ Write DROP-TABLE-stage scripts -----------
DROP TABLE IF EXISTS DBHOGE.TABLEHOGE;$$

-- ------------ Write CREATE-TABLE-stage scripts -----------
CREATE TABLE IF NOT EXISTS DBHOGE.TABLEHOGE (
ID DOUBLE NOT NULL,
COL1 VARCHAR(64) DEFAULT NULL,
COL2 DECIMAL(3,0) DEFAULT NULL,
COL3 VARCHAR(10) DEFAULT NULL,
PRIMARY KEY (ID)
) ENGINE=InnoDB;$$

-- ------------ Write CREATE-CONSTRAINT-stage scripts -----------
ALTER TABLE DBHOGE.TABLEHOGE
ADD CONSTRAINT TABLEHOGE_UNIQUE01 UNIQUE (COL1);$$

-- ------------ Write CREATE-FOREIGN-KEY-CONSTRAINT-stage scripts -----------
ALTER TABLE DBHOGE.TABLEHOGE
ADD CONSTRAINT TABLEHOGE_FKEY01 FOREIGN KEY (COL1)
REFERENCES DBHOGE.TABLEHOGE2 (ID);$$

-- ------------ Write CREATE-INDEX-stage scripts -----------
CREATE INDEX TABLEHOGE_IDX01
USING BTREE ON DBHOGE.TABLEHOGE (COL1);$$

delimiter ;

今回は試行錯誤の結果、システム移行に伴う一定時間の停止を許容していただき、change data capture(CDC)は諦めて、DMSを用いて高速にデータ転送を行い、事前に用意したSQLでスキーマ定義の修正を後から行う方針に決まりました。作業の流れとしては、高速にデータ転送できるDMSに1〜4の作業をやってもらって、5以降の作業をSCTから生成された叩き台ベースに修正したSQLを実行する、という順番でデータ移行を行いました。

  1. DB削除
  2. DB作成
  3. テーブル削除
  4. テーブル作成 〜ここまではDMSに任せた
  5. ユニークキー制約追加 〜ここから先はSCTから生成したSQLをベースに手動で操作した
  6. 外部キー制約追加
  7. インデックス追加
  8. その他のデータ、スキーマ修正

今回採用したデータ移行作業の流れを整理すると、以下のようになります。

  • DMSによるデータ移行
  • 初期転送のみで差分転送はしない
  • Migration type: Full Load
  • データベース作成、テーブル作成(主キー、データ型)はDMSに任せる
  • TargetTablePrepMode: DROP_AND_CREATE
  • SQL手動実行によるスキーマ修正
  • SCTにより生成されたSQLを叩き台として手動修正
  • ユニークキー制約追加、外部キー制約追加、インデックス追加
  • その他のデータ、スキーマ修正

ということで、移行方式が決まれば、あとは実行するだけです。DMSの具体的な操作方法は今回は割愛しますので、前回までの記事や、公式ドキュメントを見て、実際に試してみていただけたらと思います。

スキーマ移行用SQLの手動修正1: ORACLE SEQUENCE対応

今回移行元のデータベースでは、移行元でORACLE SEQUENCEを利用していたのですが、MySQLでは利用できない為、AUTO_INCREMENTで対応することになりました。また、DMSを使ったデータ移行では、ORACLEのNUMBER型がDOUBLE型やDECIMAL型でMySQLに移行されてしまった為、AUTO_INCREMENTを利用できるBIGINT型に統一して対応することにしました。

ALTER TABLE DBHOGE.TABLEHOGE MODIFY ID BIGINT NOT NULL AUTO_INCREMENT;

ちなみに、SCTのレポートでも、SEQUENCEは移行できないからがんばれと言われました。

Issue 341: MySQL doesn't support sequences
Recommended Action: Try developing a system for sequences in your application.

スキーマ移行用SQLの手動修正2: VARCAHRで大文字・小文字を区別されない問題

移行したデータで、ユニーク制約を定義するSQLを流したところ、エラーになることがありました。MySQLではVARCHARはデフォルトでは大文字・小文字を区別しないようです。大文字・小文字を区別させる為に、BINARY属性を設定する必要がありました。

ALTER TABLE DBHOGE.TABLEHOGE MODIFY COL3 CHAR(10) BINARY DEFAULT NULL;

スキーマ移行用SQLの手動修正3: DATE型の日時をCONVERT_TZで一括置換

ORACLEのDATE型でJSTで作成されたデータを、MySQLに移行時にUTCへの変換が必要となりました。今回は下記のようなSQLを用意してまとめて変換処理を行うことにしました。

UPDATE DBHOGE.TABLEHOGE2 SET DATEHOGE = CONVERT_TZ(DATEHOGE,'ASIA/Tokyo','UTC');

注意事項

その他の注意事項も記載しておきます。

注意事項1: lower_case_table_namesを後から変更しない

ORACLE環境では大文字のテーブル名をご利用の方も多いと思うのですが、mysql移行に合わせて小文字に変更しておきたくなりますよね。DBパラメータグループから、lower_case_table_namesを変更したのですが、テーブル作成後にこのパラメータを変更すると、テーブルがdropできなくなるという問題が発生しました。テーブル作成した後に、lower_case_table_namesを変更しないようにしましょう。

まとめ

試行錯誤の上でOracleからMySQLへのデータ移行を行った様子が、よくおわかりいただけたのではないでしょうか?今回移行したデータベースは、Oracle特有の機能を数多く使っていたということもありませんでしたし、データ量も極端に大きいものでもありませんでしたが、それでもなかなかスムーズには行きませんでした。データベースを移行するだけでもひと苦労なのに、異なるDBエンジン間で移行を行おうと思ったらそう簡単に行くはずもないですよね。AWSサービスを活用できるところは積極的に活用すること、そして、繰り返しますが、しっかりと検証を行うこと、が重要になると思います。データ移行は苦しいですが、1回乗り越えてしまえば、あとはAWSサービスを使い倒すだけです。

気付くのが遅れたのですが、RDS OracleからRDS Auroraへの移行手順をものすごく丁寧にわかりやすく紹介した手順が公開されていました。今回ご紹介した流れと作業の順番は異なりますが、DMS、SCTと手動でのSQL操作を組み合わせて作業している様子がよくわかる内容になっています。OracleからMySQLでもほぼ同じように使えるはずですので、ぜひこちらも読んでみてください。

どこかの誰かのお役に立てば嬉しいです。