OracleからMySQLへODBC経由のデータベースリンクで接続したメモ
Oracle Standard Editionで可能なDatabase Gateway for ODBC (DG4ODBC)
を使用してMySQLに接続したのでメモ。
Database Gateway for ODBC (DG4ODBC)
を使用すれば
ODBC接続でOracleから他のDB(MySQL)などにデータベースリンク経由で接続可能となる。
環境
DB | DBVersion | OS | IP | DB文字コード |
---|---|---|---|---|
Oracle | 11.2.0.4 SEone | Oracle Linux 6.5 | 192.168.1.11 | EUC_JP |
MySQL | 5.6.20 | CentOS 6.5 | 192.168.1.10 | EUC_JP |
以下を元にインストールと設定
Oracle Database Gateway for ODBCの構成
1.OracleサーバからODBC経由でMySQLへ接続するための設定
unixODBCのインストールと設定
unixODBCとconnectorをyumでインストールする
#yum install unixODBC #yum install mysql-connector-odbc
unixODBCの状態確認
# odbcinst -j unixODBC 2.2.14 DRIVERS............: /etc/odbcinst.ini SYSTEM DATA SOURCES: /etc/odbc.ini FILE DATA SOURCES..: /etc/ODBCDataSources USER DATA SOURCES..: /home/oracle/.odbc.ini SQLULEN Size.......: 8 SQLLEN Size........: 8 SQLSETPOSIROW Size.: 8
unixODBCのドライバーの確認
#vim /etc/odbcinst.ini [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の接続設定を行う
# vim /etc/odbc.ini [TOKDB]・・・データソース名 Driver = MySQL・・・/etc/odbcinst.iniのドライバ名 SERVER = 192.168.1.10・・・MySQLのホスト名またはIP DATABASE = KDB・・・MySQLの接続するデータベース名 PORT = 3306・・・MySQLのポート番号 PASSWORD = oraora・・・MySQLのパスワード USER = fromora・・・MySQLユーザ名
SYSTEM DATA SOURCESで設定を行うこと。
USER DATA SOURCES(/home/oracle/.odbc.ini)では動作しなかったので注意。
MySQL側の設定
IP許可をする GRANT USAGE ON *.* TO 'fromora'@'192.168.1.11' IDENTIFIED BY 'oraora'; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES, EXECUTE ON `kdb`.* TO 'fromora'@'192.168.1.11';
ODBCで接続できるかテスト
# isql -v TOKDB +---------------------------------------+ | Connected! | | | | sql-statement | | help [tablename] | | quit | | | +---------------------------------------+ SQL> select @@version; +-----------+ | @@version | +-----------+ | 5.6.20-log| +-----------+
これでOracle側のサーバからODBC接続でMySQLへ接続できることは確認できた。
2.Oracleでデータベースリンクを使ってMySQLへ接続する設定
DG4ODBCのインストール方法
2種類のインストール方法があるみたいだがOracleデータベースにインストールする。
DESCRIBE SYS.HS_FDS_CLASSがあることを確認する、あればデフォルトでインストールはされている模様。
SQL> DESCRIBE SYS.HS_FDS_CLASS 名前 NULL? 型 ----------------------------------------- -------- ---------------------------- FDS_CLASS_NAME NOT NULL VARCHAR2(30) FDS_CLASS_COMMENTS VARCHAR2(255) FDS_CLASS_ID NOT NULL NUMBER
ちなみに、なければ$ORACLE_HOME/rdbms/admin にある caths.sql をas sysdbaで実行すればいいみたい。
初期化パラメータ(initファイル)を修正する
サンプル($ORACLE_HOME/hs/admin/initdg4odbc.ora)があるので
サンプルの初期化ファイルをコピーしてその名前をinitsid.oraに変更します。
(sidは、ゲートウェイの接続先となるOracle以外のシステムのインスタンスで使用されるシステム識別子(SID)です)
mv initdg4odbc.ora inittomysql.ora
oracle$ vim inittomysql.ora HS_FDS_CONNECT_INFO = TOKDB HS_FDS_SHAREABLE_NAME = /usr/lib64/libmyodbc5.so set ODBCINI= /etc/odbc.ini
- HS_FDS_CONNECT_INFO=dsn_value(odbc.iniファイルに構成されているデータソース名)
- HS_FDS_SHAREABLE_NAME=full_path_of_odbc_driver(ODBCドライバ・マネージャのフルパス)
リスナーの追加
Oracleデータベース上で1521ポートのリスナーはすでに稼動していたのでLISTENER2(port:1522)を追加する
vim $ORACLE_HOME/network/admin/listener.ora LISTENER2 = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS =(PROTOCOL=TCP)(HOST=localhost)(PORT=1522)) ) ) ) SID_LIST_LISTENER2 = (SID_LIST = (SID_DESC = (SID_NAME=tomysql) (ORACLE_HOME=/opt/oracle/product/11.2.0/dbhome_1) (PROGRAM=DG4ODBC) ) )
起動する
$ lsnrctl start listener2 LSNRCTL for Linux: Version 11.2.0.4.0 - Production on 24-7月 -2015 14:57:19 Copyright (c) 1991, 2013, Oracle. All rights reserved. /opt/oracle/product/11.2.0/dbhome_1/bin/tnslsnrを起動しています。お待ちください... TNSLSNR for Linux: Version 11.2.0.4.0 - Production システム・パラメータ・ファイルは/opt/oracle/product/11.2.0/dbhome_1/network/admin/listener.oraです。 ログ・メッセージを/opt/oracle/diag/tnslsnr/oracle-test-db01/listener2/alert/log.xmlに書き込みました。 リスニングしています: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=1522))) TNS-01201: リスナーでは、実行可能な/opt/oracle/product/11.2.0/dbhome_1/bin/DG4ODBC(SID tomysql)を検索できません。 リスナーが起動に失敗しました。前述のエラー・メッセージを参照してください...
む、失敗した。。
/opt/oracle/product/11.2.0/dbhome_1/bin/DG4ODBC(SID tomysql)を検索できません。
確認すると
$ ls /opt/oracle/product/11.2.0/dbhome_1/bin/ | grep -i DG4ODBC dg4odbc dg4odbcO
小文字だったのね。。というわけで修正(PROGRAM=DG4ODBC)
→(PROGRAM=dg4odbc)
。
vim $ORACLE_HOME/network/admin/listener.ora SID_LIST_LISTENER2 = (SID_LIST = (SID_DESC = (SID_NAME=tomysql) (ORACLE_HOME=/opt/oracle/product/11.2.0/dbhome_1) (PROGRAM=dg4odbc) ) )
再度、起動する
$ lsnrctl start listener2 LSNRCTL for Linux: Version 11.2.0.4.0 - Production on 24-7月 -2015 14:58:13 Copyright (c) 1991, 2013, Oracle. All rights reserved. /opt/oracle/product/11.2.0/dbhome_1/bin/tnslsnrを起動しています。お待ちください... TNSLSNR for Linux: Version 11.2.0.4.0 - Production システム・パラメータ・ファイルは/opt/oracle/product/11.2.0/dbhome_1/network/admin/listener.oraです。 ログ・メッセージを/opt/oracle/diag/tnslsnr/oracle-test-db01/listener2/alert/log.xmlに書き込みました。 リスニングしています: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=1522))) (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1522)))に接続中 リスナーのステータス ------------------------ 別名 listener2 バージョン TNSLSNR for Linux: Version 11.2.0.4.0 - Production 開始日 24-7月 -2015 14:58:13 稼働時間 0 日 0 時間 0 分 0 秒 トレース・レベル off セキュリティ ON: Local OS Authentication SNMP OFF パラメータ・ファイル /opt/oracle/product/11.2.0/dbhome_1/network/admin/listener.ora ログ・ファイル /opt/oracle/diag/tnslsnr/oracle-test-db01/listener2/alert/log.xml リスニング・エンドポイントのサマリー... (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=1522))) サービスのサマリー... サービス"tomysql"には、1件のインスタンスがあります。 インスタンス"tomysql"、状態UNKNOWNには、このサービスに対する1件のハンドラがあります... コマンドは正常に終了しました。
無事リスナーの起動ができた。
tnsnames.oraの編集
vim $ORACLE_HOME/network/admin/tnsnames.ora dg4odbc= →データベース・リンクの作成時に使用する(任意の文字列) (DESCRIPTION= (ADDRESS= (PROTOCOL=TCP) (HOST=localhost) →ゲートウェイが稼働しているマシン (PORT=1522) →listener.oraで設定したポート ) (CONNECT_DATA= (SID=tomysql)) →listener.oraファイルで指定されたSID (HS=OK)) →これは必須らしい
データベースリンク作成
SQL> CREATE PUBLIC DATABASE LINK DBLINK_MYSQL CONNECT TO "fromora" IDENTIFIED BY "oraora" USING 'dg4odbc'; データベース・リンクが作成されました。
これで完成のはず。 では試してみた。
SQL> desc tt@DBLINK_MYSQL; ERROR: ORA-02085: データベース・リンクDBLINK_MYSQLはHO.WORLDに接続します
お、なんかできない。
ORA-02085
でぐぐってると、
global_namesがあやしいので確認すると
trueに設定するとデータベース・リンクが、接続するデータベースと同じ名前を持つ必要がある
SQL> SELECT VALUE FROM v$parameter WHERE NAME LIKE 'global_names'; VALUE -------------------------------------------------------------------------------- TRUE
だったのでfalseに変更
SQL> alter system set global_names= false; システムが変更されました。
再度確認。
SQL> desc tt@DBLINK_MYSQL; 名前 NULL? 型 ----------------------------------------- -------- ---------------------------- id NUMBER(10) t NVARCHAR2(10)
よし。できた!とも思ったらNVARCHAR2(10)
??
SQL> select * from tt@DBLINK_MYSQL; id t ---------- ---------------------------------------- 1 {0R0{0R0
やはり文字化けしてる。 MySQL側を確認すると
mysql> desc tt; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | t | varchar(10) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ mysql> select * from tt; +------+----------+ | id | t | +------+----------+ | 1 | ほげほげ | +------+----------+
MySQL側の文字コード(euc-jp)にあわせるのに
MySQL :: MySQL Connector/ODBC Developer Guide :: 5.2 Connector/ODBC Connection Parameters
を確認すると
/etc/odbc.iniにcharset = ujis
を追加してあげる必要があるみたい。
SQL> select * from tt@DBLINK_MYSQL; id t ---------- ------------------------------- 1 ほげほげ
これで無事できるようになった。
あとは、MySQL側のカラムにはダブルクォーテーションで囲んであげないとだめみたい。SQLPLUSだけなのかな?
SQL> select a.id,a.dbnm,b."dbnm" from ott a join tt@DBLINK_MYSQL b on a.id=b."id"; ID DBNM dbnm ---------- ---------- ------------------------------ 1 Oracle MySQL