OracleからMySQLへ定義とデータを移行(コンバート)したやり方メモ | クズリーマンのカス備忘録

OracleからMySQLへ定義とデータを移行(コンバート)したやり方メモ

animal_dolphin-iruka-mysql-logo MySQL
スポンサーリンク

そもそも、MariaDBが選択できるならそれも良いかも

今回は移行先がMySQLと決まってしまっていたため、仕方なかったが、MySQLと互換性のあるMariaDBを選択できるのであれば、MariaDBを選択したほうが楽と思われる。

なぜならMariaDBにはOracle互換モードというものがある為。

全体の流れ

今回Oracle→MySQL移行(コンバート、コピー)は、以下の流れでコンバートした。

  1. OracleからMySQL定義を移行する
    1. いくつかエラーとか出るから個別に対処する
  2. データを移行する
  3. MySQL側の定義を調整する
    1. 照合順序
    2. 文字コード
    3. 主キー
    4. UNIQUEキー
    5. 外部キー
    6. SEQUENCE
      1. MySQLの、AUTO_INCREMENT に変える
      2. または、SEQUENCEの仕組みをMySQL側に手動で作成する

 

「MySQL側の定義を調整する」は、順番としては定義の移行直後にすべきだが、あとから「あれも」「これも」設定しなければならないという感じでポロポロ出てきた。

その為、その都度MySQL側の定義を設定する。

MySQLの定義は、移行元のOracleのDDL(定義)が複雑であればあるほど、ツール一発で移行という訳には、2022年3月22日時点ではいかないので、手動で設定していって、できあがったものを正とする。

他のMySQL環境に作成したMySQL環境を移したいときはDUMPから移せばいい。

環境

 

それぞれのバージョン↓

  • Oracleのバージョンは、12c
  • MySQLのバージョンは、8.0

で実施した。

 

MySQLで大文字小文字を区別しない設定をした

Oracleでは大文字小文字を区別しなかったため、MySQLでも大文字小文字を区別しない設定にした

lower_case_table_names は、サーバーの初期化時にのみ構成できます。

MySQL8.0公式マニュアル

なので、大文字小文字を区別しない設定をする場合は、最初に忘れず設定すること。

 

MySQL側の文字セットをutf8mb4に設定

以下追記。

[mysql]
default-character-set=utf8mb4

[mysqld]
character_set_server=utf8mb4
collation-server=utf8mb4_bin
MySQL 8 のデフォルト文字セット系をすべて utf8mb4 にする cnf の書き方メモ
まとめ の default-character-set=utf8mb4 で変更される項目 ch…

(助かりました)

 

 

設定確認。

MySQLに接続して、以下実行。

mysql> SHOW VARIABLES LIKE 'character_set%' -> ;
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8mb3 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.01 sec)

mysql>

 

 

Oracle→MySQL 定義(DDL)の移行

OracleからMySQLへのテーブル定義(DDL)の移行 - Qiita
OracleからMySQLにテーブル定義をまとめて移行する方法です。経緯など開発環境以上はOracle。そこそこ制約が厳しいので、個々の開発の段階で、より自由に操作できるDB環境を整えるため。…

一部うまく行かない所があったが、こちらのQiitaの記事どおりでうまく行った。(アザス!!)

  1. SQL DeveloperでOracleからDDLのみをエクスポート
  2. sqlinesでMySQL用にDDLをコンバート
  3. mysql -f -uroot DB名 < MySQL用のDDL   で、MySQLにインポート
    1. オプション -f (Force)をつけて実行しないと駄目だった

 

いくつかエラーが出たので以下に記載する。それ以外は、問題なく、OracleからMySQLへのデータ型は同等のものが割り振られていた(MySQL用のSQLクエリに記述されていた)。

sqlines優秀。

駄目だったもの1.Oracleでの、CREATE TABLE 時に PRALLEL 句がついてるもの

Oracleでの、CREATE TABLE 時の PRALLEL ってなに?

PARALLEL句の説明

⇒https://docs.oracle.com/cd/E57425_01/121/SQLRF/statements_7002.htm

 

MySQL8 で、Parallel が使えるの(読み取りだけっぽい)innoDBみたい。

だが、インポート先のエンジンはinnoDBだったのでこの問題ではない。

とりあえず、DDLから手動でParallel句を削ってインポートしたら、

インポートできた。

 

駄目だったもの2. DECIMAL 型の第荷引数に負の数を指定している

 

MySQLのDECIMAL型

 

 

MySQLインポート時に以下のエラーが出てた。

ERROR 1064 (42000) at line 320: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-2),

インポートに失敗した部分のデータ定義を確認すると、

`カラム名` DECIMAL(7,-2), 

 

のようになってた。

DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]

M は桁数の合計 (精度) で、D は小数点以下の桁数 (スケール) です。

固定小数点数型(DECIMAL, NUMERIC)
MySQL で利用可能なデータ型の中で固定小数点数型(DECIMAL, NUMERIC)の使い方について解説します。

 

小数点以下の桁数が「-2」っておかしい ってことでしょうな。

 

OracleのNumber型

 

インポートされたデータを、Oracle側で確認してみると、Number型だった。

	"カラム名" NUMBER(7,-2), 

 

負のスケールを指定すると、Oracle Databaseにより小数点の左側の指定した桁数で実際のデータが丸められます。たとえば、(7,-2)という指定は、表26-1に示されているとおり、Oracle Databaseによって100の位で丸めることを意味します。

Oracleデータ型

Number型の第二引数で負数を指定すると、指定した桁で丸めるということらしい。

例えば、Number型の第二引数が「-2」の場合、100の桁で丸められるということだから、

7456124

7456100

となる。

 

MySQLでも、指定した桁で数字を丸めるデータ型とかあるのか?

探してみたけど、見つからなかった。

 

対応としては、一旦、

NUMBER(7,-2)  # Oracle

DECIMAL(7,0)    # MySQL

に変更して対応しようかとしたが、

データの利用目的を調べると、不要なテーブルということが分かったので、テーブルごと削除することで対応した。

 

OracleのDecimal型

 

ちなみにOracleでもDecimal型は第二引数に負数を指定できない。

DECIMAL

scaleパラメータは、小数点の右側にくる桁数のことで、スケール変更係数と呼びます。デフォルト値は0(ゼロ)です(整数となります)。全体の桁数より大きい数は指定できますが、負数は指定できません。

次に例を示します。

sal DECIMAL (7,2)

 

 

 

駄目だったもの3. DECIMAL→DECIMAL変換で、そのまま移行すると引数の右辺が左辺より大きくなってエラー

詳細は割愛するが、Oracleで、decimal(4,9) だったものが、

MySQLでdecimal(4,9)になると、引数の右辺が左辺より大きくなる。この場合だと、9が4より大きくなるのでMySQLにインポートできずエラーになる。

以下を参考にした。

 

対応としては、

Oracleの decimal(4,9) は、

MySQL側で、decimal(10,9)

にすることを考えたが、

データの利用目的を調べると、不要なテーブルということが分かったので、テーブルごと削除することで対応した。

 

Oracle→MySQL データの移行

 

実行環境の準備

まず、実行環境の準備。

  • Oracleからのエクスポートに、sql*plus
    • sqlplusの12以上(csv出力ができるVersion)
  • MySQLへのインポートに、mysql-client

が必要なので、それぞれ用意する。

 

環境変数設定(sql*plus用)

$ export LANG = ja_JP.UTF–8
$ export NLS_LANG=Japanese_Japan.AL32UTF8

 

データ移行実行

前準備

MySQL側で、ファイルからのデータインポートを許可していない場合は、以下を参考に、一時的に許可実施する。

MySQL 8.0 で LOAD DATA INFILE LOCAL を利用するには、
サーバとクライアント両方で local-infile パラメータを ON にする必要がある

https://mita2db.hateblo.jp/entry/2020/01/13/163218

サーバ側で設定。

$ mysql -uroot

mysql> SET GLOBAL local_infile=on;
Query OK, 0 rows affected (0.00 sec)

mysql>

 

この設定はMySQLを切断するともとに戻る。

 

実行

 

githubに公開してくださっているシェルスクリプトに手を加えて実行した。

手を加えたものはこちらに置いた。

 

  1. githubから上記の「こちら」ダウンロード(git clone でも可)
  2. 以下のファイルを編集して自分の環境用に書き換える
    1. 1_ora-my-convert/env.txt
      1. sql*pulsのローカルマシン内のPath 
      2. Oracleの接続情報
      3. MySQLの接続情報
    2. 1_ora-my-convert/wrap_table_record_oracle_to_mysql.sh
      1. 対象のテーブル名すべて
        1. 1行に1テーブル書く
    3. 2_ora-my-check/mysql-table-get.php
      1. 対象のテーブル名すべて
        1. 1行に1テーブル書く
  3. シェルスクリプトに実行権付与
    1. chmod + x 1_ora-my-convert/*.sh
  4. OracleからMySQLへデータ移行実行
    1. cd 1_ora-my-convert/
    2. ./wrap_table_record_oracle_to_mysql.sh

 

: end: コマンドが見つかりません のエラー
: end: コマンドが見つかりません

っていうエラーが出るのは、データの件数が0件のため。

OracleもMySQLもデータが0件なら問題ない。

データ移行後確認

OracleとMySQLそれぞれからcsvファイルにエクスポートしたものを比較することにする。

  1. シェルスクリプトに実行権付与
    1. chmod + x 2_ora-my-check/*.sh

 

    MySQLのデータ取得

    1.  MySQLからデータ取得(比較用)
      1. cd  2_ora-my-check
      2. php ./mysql-table-get.php

     

    OracleとMySQLのデータたちを比較する

     

    1. OracleとMySQLのデータ比較
      1. ./chk.sh

        1. なにも表示されなければ問題ない。
          1. chk.shの最後の行で、diffコマンドをかけている。

    Oracleからインポートできないデータがあった(データ欠損)

    Oracleからインポートできないデータがあった。

    これについては検証環境のOracleのDDLをいじることで対応した

    コメント

    タイトルとURLをコピーしました