Featured image of post Interconexión de Servidores de Bases de Datos: Oracle y PostgreSQL

Interconexión de Servidores de Bases de Datos: Oracle y PostgreSQL

Interconexión de Servidores

En este artículo detallo el proceso realizado para interconectar servidores de bases de datos Oracle y PostgreSQL en diferentes configuraciones: Oracle-Oracle, PostgreSQL-PostgreSQL y conexiones heterogéneas entre ambos sistemas.

Preparación del Entorno

Para realizar esta práctica, he partido de una máquina virtual existente (bd) que ya contaba con los servidores de base de datos instalados. He clonado esta máquina para crear un segundo nodo (bd2).

virt-clone --original bd --name bd2 --auto-clone

Configuración de red en bd2

Una vez clonada, he modificado la configuración de red de ‘bd2’ para asignarle la IP 192.168.122.127 y cambiar su hostname, evitando conflictos con la máquina original (cuya IP es 192.168.122.126).

# Cambiar IP
sudo sed -i 's/192.168.122.126/192.168.122.127/g' /etc/network/interfaces
# Cambiar hostname
sudo sed -i 's/bd/bd2/g' /etc/hosts
sudo hostnamectl set-hostname bd2

Renombrar bases de datos en bd2

PostgreSQL

En el servidor PostgreSQL de ‘bd2’, renombré la base de datos a prueba_db_2 para distinguirla claramente.

ALTER DATABASE prueba_db RENAME TO prueba_db_2;

Oracle

Para Oracle, realicé una serie de comandos para cerrar, renombrar y volver a abrir la Pluggable Database como ORCLPDB2.

ALTER PLUGGABLE DATABASE ORCLPDB1 CLOSE IMMEDIATE;
ALTER PLUGGABLE DATABASE ORCLPDB1 OPEN RESTRICTED;
ALTER PLUGGABLE DATABASE ORCLPDB1 RENAME GLOBAL_NAME TO ORCLPDB2;
ALTER PLUGGABLE DATABASE ORCLPDB2 CLOSE IMMEDIATE;
ALTER PLUGGABLE DATABASE ORCLPDB2 OPEN;
ALTER SYSTEM REGISTER;

1. Interconexión Oracle-Oracle

Configuré un Database Link para conectar desde la base de datos Oracle en bd hacia la base de datos Oracle en bd2.

Configuración en ‘bd’

Edité el archivo tnsnames.ora para definir la conexión hacia bd2.

Archivo: /opt/oracle/homes/OraDBHome21cEE/network/admin/tnsnames.ora

BD2_LINK =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.122.127)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = ORCLPDB2)
    )
  )

Configuración en ‘bd2’

Me aseguré de que el listener estuviera escuchando correctamente y creé un usuario específico para la conexión.

ALTER SYSTEM SET local_listener='(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.122.127)(PORT=1521))' SCOPE=BOTH;
ALTER SYSTEM REGISTER;

-- Crear usuario en ORCLPDB2
ALTER SESSION SET CONTAINER=ORCLPDB2;
CREATE USER serjaii IDENTIFIED BY "0191";
GRANT CONNECT, RESOURCE TO serjaii;
GRANT CREATE SESSION TO serjaii;

En bd, creé el enlace utilizando las credenciales del usuario creado anteriormente.

CREATE DATABASE LINK link_to_bd2
  CONNECT TO serjaii IDENTIFIED BY "0191"
  USING 'BD2_LINK';

Comprobación

Realicé una consulta distribuida para verificar el enlace:

SELECT e.ename AS empleado_local, d.dname AS departamento_remoto
FROM emp e
JOIN dept@link_to_bd2 d ON e.deptno = d.deptno
WHERE e.deptno = 10;

Resultado:

EMPLEADO_L DEPARTAMENTO_REMOTO
---------- ------------------
CLARK      ACCOUNTING
KING       ACCOUNTING
MILLER     ACCOUNTING

2. Interconexión PostgreSQL-PostgreSQL

Para conectar dos servidores PostgreSQL, utilicé la extensión dblink.

Configuración Previa

Es necesario asegurar que ambos servidores permitan conexiones remotas:

  • pg_hba.conf: añadir host all all 0.0.0.0/0 md5
  • postgresql.conf: establecer listen_addresses = '*'

Habilité la extensión en ambas bases de datos.

CREATE EXTENSION IF NOT EXISTS dblink;

Verificación

Probé la conexión ejecutando una consulta remota desde bd hacia bd2.

SELECT e.ename, t.dname, t.loc
FROM emp e
JOIN dblink(
  'host=192.168.122.127 user=serjaii password=0191 dbname=prueba_db_2',
  'SELECT deptno, dname, loc FROM dept'
) AS t(deptno int, dname varchar, loc varchar)
ON e.deptno = t.deptno
WHERE e.deptno = 20;

Resultado:

 ename |  dname   |  loc   
-------+----------+--------
 SMITH | RESEARCH | DALLAS
 JONES | RESEARCH | DALLAS
 SCOTT | RESEARCH | DALLAS
 ADAMS | RESEARCH | DALLAS
 FORD  | RESEARCH | DALLAS

3. Interconexión Oracle-PostgreSQL (Heterogeneous Services)

Esta configuración permite conectar desde Oracle hacia una base de datos PostgreSQL utilizando ODBC y Oracle Heterogeneous Services.

Instalación de ODBC en bd

sudo apt-get update
sudo apt-get install -y unixodbc unixodbc-dev odbc-postgresql

Configuración ODBC

Definí el Data Source Name (DSN) en /etc/odbc.ini.

[PostgreSQL_bd2]
Description=PostgreSQL connection to bd2
Driver=PostgreSQL Unicode
Servername=192.168.122.127
Port=5432
Database=prueba_db_2
Username=serjaii
Password=0191

Verifiqué la conexión con isql -v PostgreSQL_bd2.

Configuración Heterogeneous Services

Creé el archivo de inicialización del gateway.

Archivo: /opt/oracle/homes/OraDBHome21cEE/hs/admin/initpgbd2.ora

HS_FDS_CONNECT_INFO = PostgreSQL_bd2
HS_FDS_TRACE_LEVEL = DEBUG
# Apuntar a la librería correcta es CRÍTICO para evitar errores
HS_FDS_SHAREABLE_NAME = /usr/lib/x86_64-linux-gnu/libodbc.so
set ODBCINI=/etc/odbc.ini
set LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/odbc

Configuración de Listener y TNS

Archivo: listener.ora

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = pgbd2)
      (ORACLE_HOME = /opt/oracle/product/21c/dbhome_1)
      (PROGRAM = dg4odbc)
      (ENVS="ODBCINI=/home/oracle/odbc.ini") 
    )
  )

Nota: Es importante asegurar que el usuario Oracle tenga acceso al archivo odbc.ini, a veces es necesario copiarlo a su home o definir la variable ENVS adecuadamente.

Archivo: tnsnames.ora

PGBD2 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.122.126)(PORT = 1521))
    (CONNECT_DATA = (SID = pgbd2))
    (HS = OK)
  )

Recargué el listener con lsnrctl reload.

CREATE DATABASE LINK link_to_postgres
  CONNECT TO "serjaii" IDENTIFIED BY "0191"
  USING 'PGBD2';

Solución de Errores Comunes

Durante el proceso encontré el error ORA-28500 con mensaje [unixODBC][Driver Manager]Data source name not found. Esto se debió a que el proceso del listener no encontraba el archivo odbc.ini. La solución fue configurar explícitamente la variable de entorno ODBCINI en el listener.ora o asegurar permisos de lectura para el usuario oracle. También corregí el HS_FDS_SHAREABLE_NAME para apuntar a libodbc.so en lugar del driver de Postgres directamente.

Verificación

SELECT e.ename, e.job, e.sal
FROM emp e
WHERE e.sal > (SELECT AVG("sal") FROM "emp"@link_to_postgres);

Resultado:

ENAME     JOB       SAL
--------- --------- ---------
JONES     MANAGER   2975
BLAKE     MANAGER   2850
CLARK     MANAGER   2450
SCOTT     ANALYST   3000
KING      PRESIDENT 5000
FORD      ANALYST   3000

4. Interconexión PostgreSQL-Oracle

Para conectar desde PostgreSQL hacia Oracle, utilicé la extensión oracle_fdw.

Instalación

sudo apt-get install -y postgresql-server-dev-all build-essential unzip

# Descargar y compilar oracle_fdw
wget https://github.com/laurenz/oracle_fdw/archive/refs/heads/master.zip
unzip master.zip
cd oracle_fdw-master
export ORACLE_HOME=/opt/oracle/product/21c/dbhome_1
make
sudo make install

Configuré las librerías dinámicas para que PostgreSQL encuentre las de Oracle:

echo "/opt/oracle/product/21c/dbhome_1/lib" | sudo tee /etc/ld.so.conf.d/oracle.conf
sudo ldconfig
sudo systemctl restart postgresql

Configuración en PostgreSQL

En la base de datos prueba_db:

CREATE EXTENSION oracle_fdw;

-- Crear el servidor foráneo
CREATE SERVER oracle_bd2 FOREIGN DATA WRAPPER oracle_fdw
OPTIONS (dbserver '//192.168.122.127:1521/ORCLPDB2');

-- Mapeo de usuario
CREATE USER MAPPING FOR serjaii SERVER oracle_bd2
OPTIONS (user 'serjaii', password '0191');

-- Importar esquema
IMPORT FOREIGN SCHEMA "SERJAII" LIMIT TO ("EMP", "DEPT")
FROM SERVER oracle_bd2 INTO public;

Verificación

SELECT ename, job, sal FROM "EMP" WHERE deptno = 10;

Resultado:

 ename  |    job    |   sal   
--------+-----------+---------
 CLARK  | MANAGER   | 2450.00
 KING   | PRESIDENT | 5000.00
 MILLER | CLERK     | 1300.00
Built with Hugo
Theme Stack designed by Jimmy