MySQLからOracleへmysqldump以外の方法でデータ移行ができないか模索するためDB LINKを作ってみました。
目指すのはOracleからMySQLのデータを取り出すこと。
手順はkenken0807さんの検証とほほ同じ。
ただUTF8環境の場合は独自のハマりポイントもあったためそちらについても記載しています。
調べてみるまではネット上にナレッジがいっぱい落ちていると思ってたのに、全然なかったしね。
少しでも参考になれば幸いです。
環境
RDBMS | DB version | OS | OS version | IP address | DBの文字コード |
---|---|---|---|---|---|
Oracle | 18.3.0.0.0 | Oracle Linux | 7.6 | 192.168.56.101 | utf8 |
MySQL | 5.7.25 | Oracle Linux | 7.6 | 192.168.56.111 | utf8 |
MySQL側作業
先にDB LINK用ユーザの作成と権限の付与を行っておきます。
1. DB LINK用ユーザの作成
create user 'from_oracle'@'192.168.56.101' identified by 'from_oracle';
2. DB LINK用ユーザに接続先データベースへの権限付与
grant all privileges on db_migration.* to 'from_oracle'@'192.168.56.101';
Oracle側作業
MySQLとはODBCを経由してDB LINKを行います。
3. unixODBC (ODBC Driver Manager)のインストール
yum install unixODBC
unixODBCの設定を確認
odbcinst -j
[root@local01 ~]# odbcinst -j
unixODBC 2.3.1
DRIVERS............: /etc/odbcinst.ini
SYSTEM DATA SOURCES: /etc/odbc.ini
FILE DATA SOURCES..: /etc/ODBCDataSources
USER DATA SOURCES..: /root/.odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8
[root@local01 ~]#
SYSTEM DATA SOURCESのパスを確認しておく。
4. mysql-connector-odbc (MySQL用ODBCドライバ) のインストール
Oracle Linuxのリポジトリ [ol7_latest] から入手するとドライバのバージョンが結構古い(5.2.5-8)ので、公式から最新版をインストール。
yum install https://dev.mysql.com/get/Downloads/Connector-ODBC/8.0/mysql-connector-odbc-8.0.15-1.el7.x86_64.rpm
最新版はこちらからも入手可能。
http://dev.mysql.com/downloads/connector/odbc/#downloads
5. unixODBCのMySQL用ODBC Driverの設定確認
unixODBCおよびmysql-connector-odbcのインストールを行うと、自動的に作成&エントリーの追加がされているはず。
cat /etc/odbcinst.ini
[PostgreSQL]
Description=ODBC for PostgreSQL
Driver=/usr/lib/psqlodbcw.so
Setup=/usr/lib/libodbcpsqlS.so
Driver64=/usr/lib64/psqlodbcw.so
Setup64=/usr/lib64/libodbcpsqlS.so
FileUsage=1
[MySQL]
Description=ODBC for MySQL
Driver=/usr/lib/libmyodbc5.so
Setup=/usr/lib/libodbcmyS.so
Driver64=/usr/lib64/libmyodbc5.so
Setup64=/usr/lib64/libodbcmyS.so
FileUsage=1
[MySQL ODBC 8.0 Unicode Driver] # ★今回使用するのはこのODBCドライバ
Driver=/usr/lib64/libmyodbc8w.so
UsageCount=1
[MySQL ODBC 8.0 ANSI Driver]
Driver=/usr/lib64/libmyodbc8a.so
UsageCount=1
6. MySQLデータソースの設定
項番3で確認したSYSTEM DATA SOURCESのファイルを編集する。
vi /etc/odbc.ini
Driverには項番5で確認したドライバの名前を入れる。
データベース名の大文字小文字にも要注意。
# 任意のデータソース名
[MYDB]
# /etc/odbcinst.iniのドライバ名
# 8.0系かつUnicodeのDriverを利用
Driver = MySQL ODBC 8.0 Unicode Driver
# MySQLのホスト名またはIPアドレス
SERVER = 192.168.56.111
# MySQLのポート番号
PORT = 3306
# MySQLの接続するデータベース名
DATABASE = db_migration
# MySQLへ接続するユーザ名
USER = from_oracle
# MySQLへ接続するユーザのパスワード
PASSWORD = from_oracle
# キャラクタセット
CHARSET = utf8
7. ODBC接続チェック
isqlコマンドを使用してODBC接続してみる。
isql MYDB -v
[root@local01 ~]# isql MYDB -v
+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
SQL> select user();
+----------------------------------------------------------------------------------------------+
| user() |
+----------------------------------------------------------------------------------------------+
| from_oracle@192.168.56.101 |
+----------------------------------------------------------------------------------------------+
SQLRowCount returns 1
1 rows fetched
SQL> show databases;
+-----------------------------------------------------------------+
| Database |
+-----------------------------------------------------------------+
| information_schema |
| db_migration |
+-----------------------------------------------------------------+
SQLRowCount returns 2
2 rows fetched
SQL> quit
[root@local01 ~]#
8. ODBCドライバマネージャーライブラリのパスを確認
項番11のゲートウェイ初期化パラメータファイル設定時に使用するため事前に確認する。
ldd `which isql`
[root@local01 ~]# ldd `which isql`
linux-vdso.so.1 => (0x00007fff38bb9000)
libodbc.so.2 => /lib64/libodbc.so.2 (0x00007ffa4a18e000) # ★ここがODBCドライバマネージャーライブラリのパス
libltdl.so.7 => /lib64/libltdl.so.7 (0x00007ffa49f84000)
libreadline.so.6 => /lib64/libreadline.so.6 (0x00007ffa49d3d000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007ffa49b39000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007ffa4991d000)
libc.so.6 => /lib64/libc.so.6 (0x00007ffa4954f000)
libtinfo.so.5 => /lib64/libtinfo.so.5 (0x00007ffa49325000)
/lib64/ld-linux-x86-64.so.2 (0x0000558bd097b000)
[root@local01 ~]#
9. listener.oraの編集
既存のリスナーに影響を与えぬよう、別途1522ポートでゲートウェイ用リスナーを作成してます。
vi ${ORACLE_HOME}/network/admin/listener.ora
下記エントリーを追記。
SID_NAMEには/etc/odbc.iniで定義したデータソース名を。
dg4odbcは小文字で。
LISTENER2 =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.56.101)(PORT = 1522))
)
)
SID_LIST_LISTENER2 =
(SID_LIST =
(SID_DESC =
(SID_NAME = MYDB)
(ORACLE_HOME = /opt/oracle/product/18c/dbhome_1)
(PROGRAM = dg4odbc)
)
)
10. tnsnames.oraの編集
vi ${ORACLE_HOME}/network/admin/tnsnames.ora
ゲートウェイ用の下記エントリーを追加する。
SIDにはlistener.oraで指定したSID_NAMEを。
MYDB =
(DESCRIPTION=
(ADDRESS=
(PROTOCOL=TCP)
(HOST=192.168.56.101)
(PORT=1522)
)
(CONNECT_DATA=
(SID = MYDB)
)
(HS=OK)
)
11. ゲートウェイ初期化パラメータファイルを作成
ゲートウェイ初期化パラメータファイルは$ORACLE_HOME/hs/admin配下にinit<SID>.oraと言う名前で作成する。
initdg4odbc.oraというサンプルファイルがあるので、それをコピーして作ってもいい。
<SID>は/etc/odbc.iniのデータソース名(DSN)とイコール。
データソース名を大文字にしている場合は初期化パラメータファイルも大文字で作る必要がある。
vi ${ORACLE_HOME}/hs/admin/initMYDB.ora
以下の内容を記載。
# /etc/odbc.iniのデータソース名
HS_FDS_CONNECT_INFO=MYDB
# Oracleの文字コードがUTF8の場合以下の通りに設定する
HS_NLS_NCHAR=UCS2
HS_LANGUAGE=JAPANESE_JAPAN.AL32UTF8
# 7.で確認したODBCドライバマネージャーライブラリのパス
HS_FDS_SHAREABLE_NAME=/lib64/libodbc.so.2
# ODBCINI変数に参照するiniファイルのパスを指定
set ODBCINI=/etc/odbc.ini
特にHS_NLS_NCHAR, HS_LANGUAGEの設定がうまくいっていないとDB LINK設定後、MySQLのデータを参照しようとしても以下のエラーが出てハマる。
ERROR at line 1:
ORA-28500: connection from ORACLE to a non-Oracle system returned this message:
[
うまくいかないときは、HS_FDS_TRACE_LEVEL=debug
を設定すること。
$ORACLE_HOME/hs/logにトレースファイルが出力されるようになるのでエラー原因が掴めるかも…。
12. リスナー起動
作成したリスナーを起動する。
lsnrctl start listener2
13. DB LINK作成
今回はPDB上でDB LINKを作成してますが、特にPDBだからうまくいかないと言ったことはありませんでした。
CREATE PUBLIC DATABASE LINK DBLINK_MYSQL CONNECT TO "from_oracle" IDENTIFIED BY "from_oracle" USING 'MYDB';
14. MySQLのデータ参照
SQL> select count(*) from "emp"@DBLINK_MYSQL;
COUNT(*)
----------
10
SQL> select "id", "desc" from "emp"@DBLINK_MYSQL where rownum <= 1;
id desc
------- ----------------------------------------
1 説明あれこれ
終わりに
実際にはかなりの試行錯誤がありました。
DB LINKを使うことでmysqldumpではできない、段階的なデータ移行ができたらいいなと思ってます。
参考にしたサイト
OracleからMySQLへODBC経由のデータベースリンクで接続したメモ
http://kenken0807.hatenablog.com/entry/2015/07/27/144953
Oracle HS fails to operate on mysql-connector-odbc-5.3.4-1.el7
https://bugs.mysql.com/bug.php?id=78242
https://bugs.mysql.com/file.php?id=23311&bug_id=78242
Error Ora-28500 and Sqlstate I or Displays a Square Bracket - [ - Issuing Selects From a Unicode Oracle RDBMS With Dg4odbc To Non-Oracle Databases Using the UnixODBC Driver Manager (ドキュメントID 756186.1)
https://support.oracle.com/epmos/faces/DocumentDisplay?id=756186.1
(参照にはOTNアカウントが必要)