DBLinks desde Oracle hacia MySQL

A menudo nos encontramos con organizaciones que tienen ya implantados diferentes entornos para el almacenamiento de la información. Es habitual encontrar una base de datos Oracle para las aplicaciones más importantes con la lógica del negocio, escritas en Oracle Forms y Java, y luego, otras bases de datos (MySQL, Postgres) asociadas a proyectos OpenSource que han decidido usar, porque cubren con total garantía nuevas necesidades que en otro caso serían muy costosas de desarrollar en tiempo y dinero.

En este escenario, suele aparecer la necesidad de vincular información desde el servidor Oracle hacia otras bases de datos como MySQL. Un ejemplo habitual es encontrar la base de datos de nuestros clientes en Oracle, mantenidos desde una aplicación Oracle Forms, y en un momento dado se quiere sincronizar los datos de contacto de estos clientes, con nuestra centralita Asterisk (que usa MySQL) de forma que, cuando la aplicación actualice los datos de algún cliente automáticamente estén disponibles para Asterisk.

Si las dos bases de datos fueran Oracle, podríamos resolverlo mediante un DBLink desde la base de datos de clientes hacia la de Asterisk y desarrollar un pequeño trigger PL/SQL para que cuando se actualicen ciertos datos, automáticamente se actualicen las tablas que lee Asterisk. Al estar este sobre MySQL, no podemos crear un DBLink. Afortunadamente Oracle contempla este escenario a través de Heterogeneus Service (HS) junto a Oracle Database Gateway for ODBC (hs4odbc).



Para configurar este servicio, tendremos que:

  1. Lo primero será comprobar que instalamos en nuestro servidor Oracle el servicio, chequeando que existe el ejecutable $ORACLE_HOME/bin/dg4odbc
  2. Lo siguiente será instalar el driver ODBC para MySQL, en nuestro servidor Oracle:
    yum install  unixODBC.x86_64 mysql-connector-odbc.x86_64 
  3. Ahora, en nuestro servidor MySQL, crearemos un base de datos de prueba, a la que conectar desde Oracle, (cualquiera sabe lo que podría hacernos en MySQL un administrador/desarrollador de Oracle)
    mysql> create database oracletest character set latin1;

    mysql> grant all privileges on oracletest.* to 'oracleconn'@'%'
    identified by 'demo' with grant option;

    mysql> flush privileges;

    mysql> exit;
    Es importante usar latin1 para la Base de datos, porque en caso de usar UTF8, tendremos problemas al acceder desde Oracle.
  4. Ahora, desde el servidor Oracle, probar a conectar al servidor MySQL, usando el cliente MySQL:
    mysql -h SERVIDOR_MYSQL  --user=oracleconn --password=demo oracletest 
    ... y una vez nos hayamos conectado, crearemos una pequeña tabla:
    create table demo (
    col1 integer,
    col2 date,
    col3 varchar(10),
    col4 varchar(10) character set utf8,
    col5 varbinary(10)) engine innodb;
    ... y aprovecharemos para insertar algún registro...
    insert into demo(col1, col2, col3, col4, col5)
    values(1, cast(now() as date), '0123456789', '0123456789', '0123456789');
  5. Ahora desde el servidor Oracle, editar el fichero ~oracle/.odbc.ini y configurar el acceso a MySQL vía ODBC, escribiendo el siguiente contenido:
    [ODBC Data Sources]
    test_mysql = MySQL ODBC Driver 5.1

    [test_mysql]
    Driver = /usr/lib64/libmyodbc3.so
    DATABASE = oracletest
    DESCRIPTION = Conexion a MySQL ODBC
    PORT = 3306
    SERVER = SERVIDOR_MYSQL# UID = oracleconn
    # PWD = demo

    CHARSET = latin1
    TRACEFILE = /tmp/myodbc-demodsn.trc
    TRACE = ON
  6. Crear el fichero $ORACLE_HOME/hs/admin/initMysql.ora. El nombre Mysql será el SID, y es un nombre arbitrario: Cualquiera que se cree, debe ser $ORACLE_HOME/hs/admin/init$SID.ora
    #
    # HS init parameters
    #

    HS_FDS_CONNECT_INFO=test_mysql
    HS_FDS_TRACE_LEVEL=0
    HS_FDS_SHAREABLE_NAME=/usr/lib64/libmyodbc3.so
    HS_LANGUAGE=AMERICAN_AMERICA.WE8ISO8859P15
    # HS_NLS_NCHAR=AL32UTF8
    #
    # ODBC specific environment variables
    #

    set ODBCINI=/home/oracle/.odbc.ini
    set LD_LIBRARY_PATH=/usr/lib64:/lib64:/usr/local/lib64:/u01/oracle/soft/product/11.1.0/db_1/lib:/u01/oracle/soft/product/11.1.0/db_1/oracm/lib:/lib:/usr/lib:/usr/local/lib

    #
    # Environment variables required for the non-Oracle system
    #

    set HOME=/home/oracle
  7. Añadir a $ORACLE_HOME/network/admin/listener.ora dentro del SID_LIST, el siguiente bloque SID_DESC:
        (SID_DESC =
    (ORACLE_HOME = /u01/oracle/soft/product/11.1.0/db_1)
    (SID_NAME = Mysql)
    (PROGRAM = dg4odbc)
    (ENVS ="LD_LIBRARY_PATH=/usr/lib64:/lib64:/usr/local/lib64:/u01/oracle/soft/product/11.1.0/db_1/lib:/u01/oracle/soft/product/11.1.0/db_1/oracm/lib:/lib:/usr/lib:/usr/local/lib")
    )
  8. Reiniciar el listener de Oracle...
    su - oracle
    lsnrctl stop
    lsnrctl start
  9. Ahora editar el fichero $ORACLE_HOME/network/admin/tnsnames.ora y añadir el siguiente bloque:
    DEMOMYSQL =
    (DESCRIPTION =
    (ADDRESS_LIST =
    (ADDRESS = (PROTOCOL = TCP)
    (HOST = localhost)
    (PORT = 1521)
    )
    )
    (CONNECT_DATA =
    (SID = Mysql)
    )
    (HS = OK)
    )
  10. Comprobar que está accesible...
    tnsping demoMYSQL
  11. Crear un DBLINK para acceder a MySQL desde nuestro servidor Oracle...
    su - oracle

    $ sqlplus / as sysdba;

    SQL> CREATE PUBLIC DATABASE LINK dbtestmysql
    CONNECT TO oracleconn
    IDENTIFIED BY demo
    USING 'DEMOMYSQL';
  12. .. y probar que funciona...
    su - oracle

    $ sqlplus / as sysdba;

    SQL> select * from demo@dbtestmysql ;
    Si estás usando Oracle 11.1.0.6 no te funcionará: Necesitas actualizar tu servidor a 11.1.0.7, porque una de los fallos que arregla tiene que ver con hs4odbc.

4 comentarios:

Unknown dijo...

Hola, muy bueno el procedimiento. Lo relicé y me funcionó. Tengo un problema al ejecutar query's parametrizadas, me da un error ORA-02070.
Estoy usando oracle 11.2.0.2 y mysql 5.1.61
Me podés ayudar. Muchas Gracias.
Saludos.

Unknown dijo...

Hola, muy bueno el articulo. Segui tu procedimiento y funciono. ahora estoy teniendo errores cuando ejecuto consultas parametrizadas desde el oracle al mysql. Me podes ayudar?
Desde ya gracias y Saludos.

Diego Ferreira.

Ignacio Barrancos dijo...

Decidme por favor qué consulta lanzais.

Angie dijo...

Hola, muchas gracias por tu procedimiento, hoy mismo voy a probarlo porque lo explicas mejor que el propio metalink.