Las interconexiones de servidores de bases de datos son operaciones que pueden ser muy útiles en diferentes contextos. Básicamente, se trata de acceder a datos que no están almacenados en nuestra base de datos, pudiendo combinarlos con los que ya tenemos.
En este artículo veremos varias formas de crear un enlace entre distintos servidores de bases de datos. Los servidores enlazados siempre estarán instalados en máquinas diferentes.
Es muy importante recordar que los enlaces son unidireccionales, es decir, si creamos un enlace en el servidor1 hacia el servidor2, será el servidor1 el que pueda acceder a los datos del servidor2, pero el servidor2 no podrá acceder a los datos del servidor1.
Hay que decir que trabajaré sobre los escenarios creados en el post anterior, que trataba sobre Instalación de Servidores y Clientes de bases de datos, por lo que ya dispongo de los servidores instalados y con las configuraciones básicas.
Enlace entre dos servidores de bases de datos ORACLE
En este primer caso, vamos a ver que configuraciones son necesarias para enlazar dos servidores Oracle. Ambos servidores se encuentran instalados sobre Windows, aunque esto no es algo que influya en el proceso.
Nos situamos en la primera de las máquinas, que recordemos que recibe el nombre de servidor.
Nos dirigiremos a los ficheros listener.ora
y tnsnames.ora
, ambos se encuentran en la ruta $ORACLE_HOME/network/admin/
, ya que en ellos es donde realizaremos la configuración.
Primeramente, para habilitar el acceso remoto al servidor, debemos modificar el fichero listener.ora
. Por defecto, posee este aspecto:
SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (SID_NAME = CLRExtProc) (ORACLE_HOME = C:\Users\servidor\Desktop\WINDOWS.X64_193000_db_home) (PROGRAM = extproc) (ENVS = "EXTPROC_DLLS=ONLY:C:\Users\servidor\Desktop\WINDOWS.X64_193000_db_home\bin\oraclr19.dll") ) ) LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521)) ) )
Si nos fijamos, dentro del bloque LISTENER, en la línea que define la regla para el protocolo TCP, que es la que nos interesa, podemos ver que en el campo HOST está configurado para que solo escuche las peticiones cuyo origen es localhost. También está configurado para que el puerto por el que escuche sea el 1521, que es el que viene configurado por defecto, a mí me vale, por eso lo dejo. Obviamente lo que hay que cambiar es el valor del campo HOST, y establecerle como valor la interfaz desde la que queremos escuchar las peticiones. En mi caso, voy a especificar el nombre de mi máquina para que así escuche todas las peticiones.
SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (SID_NAME = CLRExtProc) (ORACLE_HOME = C:\Users\servidor\Desktop\WINDOWS.X64_193000_db_home) (PROGRAM = extproc) (ENVS = "EXTPROC_DLLS=ONLY:C:\Users\servidor\Desktop\WINDOWS.X64_193000_db_home\bin\oraclr19.dll") ) ) LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = DESKTOP-IGG1O7P)(PORT = 1521)) (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521)) ) )
Una vez hemos realizado este cambio, podemos iniciar el listener. El listener se maneja con estos comandos:
- lsnrctl start: inicia el servicio.
- lsnrctl stop: detiene el servicio.
- lsnrctl status: muestra información sobre el estado.
Lo iniciamos:
C:\Windows\System32>lsnrctl start LSNRCTL for 64-bit Windows: Version 19.0.0.0.0 - Production on 17-DIC-2020 14:07:48 Copyright (c) 1991, 2019, Oracle. All rights reserved. Iniciando tnslsnr: espere... TNSLSNR for 64-bit Windows: Version 19.0.0.0.0 - Production El archivo de parßmetros del sistema es C:\Users\javier\Desktop\WINDOWS.X64_193000_db_home\network\admin\listener.ora Mensajes de log escritos en C:\Users\javier\Desktop\diag\tnslsnr\DESKTOP-IGG1O7P\listener\alert\log.xml Recibiendo en: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=DESKTOP-IGG1O7P)(PORT=1521))) Recibiendo en: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(PIPENAME=\\.\pipe\EXTPROC1521ipc))) Conectßndose a (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=DESKTOP-IGG1O7P)(PORT=1521))) ESTADO del LISTENER ------------------------ Alias LISTENER Versi¾n TNSLSNR for 64-bit Windows: Version 19.0.0.0.0 - Production Fecha de Inicio 28-ENE-2020 14:07:52 Tiempo Actividad 0 dÝas 0 hr. 0 min. 10 seg. Nivel de Rastreo off Seguridad ON: Local OS Authentication SNMP OFF Parßmetros del Listener C:\Users\javier\Desktop\WINDOWS.X64_193000_db_home\network\admin\listener.ora Log del Listener C:\Users\javier\Desktop\diag\tnslsnr\DESKTOP-IGG1O7P\listener\alert\log.xml Recibiendo Resumen de Puntos Finales... (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=DESKTOP-IGG1O7P)(PORT=1521))) (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(PIPENAME=\\.\pipe\EXTPROC1521ipc))) Resumen de Servicios... El servicio "CLRExtProc" tiene 1 instancia(s). La instancia "CLRExtProc", con estado UNKNOWN, tiene 1 manejador(es) para este servicio... El comando ha terminado correctamente
Vemos que lo ha iniciado correctamente. Ahora, para asegurarnos que realmente está escuchando peticiones desde el puerto 1521 vamos a utilizar el comando netstat
:
C:\Users\servidor>netstat Conexiones activas Proto Dirección local Dirección remota Estado TCP 127.0.0.1:1521 DESKTOP-IGG1O7P:49692 ESTABLISHED TCP 127.0.0.1:49692 DESKTOP-IGG1O7P:1521 ESTABLISHED TCP [fe80::c9ee:eb4d:5f0b:a64f%4]:49703 DESKTOP-IGG1O7P:1521 TIME_WAIT
Vemos que efectivamente está escuchando en dicho puerto.
Hecho esto, ya habríamos habilitado al servidor para que permita el acceso remoto, por tanto, vamos a dirigirnos al segundo y último fichero de configuración, el llamado tnsnames.ora
, que por defecto posee esta configuración:
LISTENER_ORCL = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) ORACLR_CONNECTION_DATA = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521)) ) (CONNECT_DATA = (SID = CLRExtProc) (PRESENTATION = RO) ) ) ORCL = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = orcl) ) )
Editaremos el último bloque que definirá la conexión con el segundo servidor Oracle, quedando de esta manera:
ORCL = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.56)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = orcl) ) )
Una vez modificado este fichero, debemos parar el proceso listener y volverlo a iniciar para que así se apliquen los nuevos cambios.
C:\Windows\system32>lsnrctl stop LSNRCTL for 64-bit Windows: Version 19.0.0.0.0 - Production on 03-FEB-2021 17:53:36 Copyright (c) 1991, 2019, Oracle. All rights reserved. Conectßndose a (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=DESKTOP-IGG1O7P)(PORT=1521))) El comando ha terminado correctamente C:\Windows\system32>lsnrctl start LSNRCTL for 64-bit Windows: Version 19.0.0.0.0 - Production on 03-FEB-2021 17:53:58 Copyright (c) 1991, 2019, Oracle. All rights reserved. Iniciando tnslsnr: espere... TNSLSNR for 64-bit Windows: Version 19.0.0.0.0 - Production El archivo de parßmetros del sistema es C:\Users\servidor\Desktop\WINDOWS.X64_193000_db_home\network\admin\listener.ora Mensajes de log escritos en C:\Users\servidor\Desktop\diag\tnslsnr\DESKTOP-IGG1O7P\listener\alert\log.xml Recibiendo en: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=DESKTOP-IGG1O7P)(PORT=1521))) Recibiendo en: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(PIPENAME=\\.\pipe\EXTPROC1521ipc))) Conectßndose a (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=DESKTOP-IGG1O7P)(PORT=1521))) ESTADO del LISTENER ------------------------ Alias LISTENER Versi¾n TNSLSNR for 64-bit Windows: Version 19.0.0.0.0 - Production Fecha de Inicio 03-FEB-2021 17:54:02 Tiempo Actividad 0 dÝas 0 hr. 0 min. 10 seg. Nivel de Rastreo off Seguridad ON: Local OS Authentication SNMP OFF Parßmetros del Listener C:\Users\servidor\Desktop\WINDOWS.X64_193000_db_home\network\admin\listener.ora Log del Listener C:\Users\servidor\Desktop\diag\tnslsnr\DESKTOP-IGG1O7P\listener\alert\log.xml Recibiendo Resumen de Puntos Finales... (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=DESKTOP-IGG1O7P)(PORT=1521))) (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(PIPENAME=\\.\pipe\EXTPROC1521ipc))) Resumen de Servicios... El servicio "CLRExtProc" tiene 1 instancia(s). La instancia "CLRExtProc", con estado UNKNOWN, tiene 1 manejador(es) para este servicio... El comando ha terminado correctamente C:\Windows\system32>
Bien, ahora debemos dirigirnos al segundo servidor, que es al que vamos a realizarle la consulta, y en su fichero listener.ora
, habilitar el acceso remoto como hicimos anteriormente:
SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (SID_NAME = CLRExtProc) (ORACLE_HOME = C:\Users\servidor\Desktop\WINDOWS.X64_193000_db_home) (PROGRAM = extproc) (ENVS = "EXTPROC_DLLS=ONLY:C:\Users\servidor\Desktop\WINDOWS.X64_193000_db_home\bin\oraclr19.dll") ) ) LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = DESKTOP-IGG1O7P)(PORT = 1521)) (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521)) ) )
Cuando hayamos realizado la modificación, iniciaremos de nuevo el listener y aplicaremos los cambios:
C:\Windows\system32>lsnrctl start LSNRCTL for 64-bit Windows: Version 19.0.0.0.0 - Production on 03-FEB-2021 18:02:49 Copyright (c) 1991, 2019, Oracle. All rights reserved. Iniciando tnslsnr: espere... TNSLSNR for 64-bit Windows: Version 19.0.0.0.0 - Production El archivo de parßmetros del sistema es C:\Users\servidor\Desktop\WINDOWS.X64_193000_db_home\network\admin\listener.ora Mensajes de log escritos en C:\Users\servidor\Desktop\diag\tnslsnr\DESKTOP-IGG1O7P\listener\alert\log.xml Recibiendo en: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=DESKTOP-IGG1O7P)(PORT=1521))) Recibiendo en: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(PIPENAME=\\.\pipe\EXTPROC1521ipc))) Conectßndose a (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=DESKTOP-IGG1O7P)(PORT=1521))) ESTADO del LISTENER ------------------------ Alias LISTENER Versi¾n TNSLSNR for 64-bit Windows: Version 19.0.0.0.0 - Production Fecha de Inicio 03-FEB-2021 18:02:55 Tiempo Actividad 0 dÝas 0 hr. 0 min. 12 seg. Nivel de Rastreo off Seguridad ON: Local OS Authentication SNMP OFF Parßmetros del Listener C:\Users\servidor\Desktop\WINDOWS.X64_193000_db_home\network\admin\listener.ora Log del Listener C:\Users\servidor\Desktop\diag\tnslsnr\DESKTOP-IGG1O7P\listener\alert\log.xml Recibiendo Resumen de Puntos Finales... (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=DESKTOP-IGG1O7P)(PORT=1521))) (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(PIPENAME=\\.\pipe\EXTPROC1521ipc))) Resumen de Servicios... El servicio "CLRExtProc" tiene 1 instancia(s). La instancia "CLRExtProc", con estado UNKNOWN, tiene 1 manejador(es) para este servicio... El comando ha terminado correctamente
Cuando ya poseamos todas las configuraciones listas, vamos a proceder a crear la conexión entre los servidores.
Pero antes de esto, voy a crear un usuario y alguna tabla que poder consultar, ya que este servidor, es totalmente virgen, por decirlo de alguna forma:
C:\Windows\system32>sqlplus SQL*Plus: Release 19.0.0.0.0 - Production on MiÚ Feb 3 18:06:19 2021 Version 19.3.0.0.0 Copyright (c) 1982, 2019, Oracle. All rights reserved. Introduzca el nombre de usuario: system Introduzca la contrase±a: Hora de ┌ltima Conexi¾n Correcta: Jue Ene 28 2021 18:56:11 +01:00 Conectado a: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production Version 19.3.0.0.0 SQL> CREATE USER c##javierserv2 IDENTIFIED BY contraseña; Usuario creado. SQL> GRANT ALL PRIVILEGES TO c##javierserv2; Concesi¾n terminada correctamente.
Vamos a crear la tabla Empleados, que será la que consultaremos luego a partir de este script.
Ahora sí, vamos a crear el propio enlace.
Para ello nos dirigimos al primer servidor y con el usuario sys, crearemos el enlace hacia el segundo servidor.
La sintaxis para crear un enlace es la siguiente:
create database link linkserv2 connect to c##javierserv2 identified by contraseña using 'orcl';
Vemos el resultado de la creación del enlace:
C:\Windows\system32>sqlplus SQL*Plus: Release 19.0.0.0.0 - Production on MiÚ Feb 3 18:07:21 2021 Version 19.3.0.0.0 Copyright (c) 1982, 2019, Oracle. All rights reserved. Introduzca el nombre de usuario: system Introduzca la contrase±a: Hora de ┌ltima Conexi¾n Correcta: Mar Ene 19 2021 19:32:59 +01:00 Conectado a: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production Version 19.3.0.0.0 SQL> create database link linkserv2 2 connect to c##javierserv2 3 identified by contraseña 4 using 'orcl'; Enlace con la base de datos creado.
Vamos a probar a hacer una consulta desde el primer servidor a la tabla Empleados que acabamos de crear y se encuentra en el segundo servidor:
SQL> select * from empleados@linkserv2; NIF --------- NOMBRE -------------------------------------------------------------------------------- ANYONACIMIENTO COD_TI -------------- ------ 12345678A Rodrigo Fernandez 1974 000001 12345678B Cristina Perez 1976 000002 NIF --------- NOMBRE -------------------------------------------------------------------------------- ANYONACIMIENTO COD_TI -------------- ------ 12345678C Ramon Fuentes 1983 000003 12345678D Maria Diaz NIF --------- NOMBRE -------------------------------------------------------------------------------- ANYONACIMIENTO COD_TI -------------- ------ 1969 000004 12345678E Alejandro Cortes 1978 000005
¡Bien! Ya tenemos el enlace creado y utilizable, y por último vamos a realizar una consulta combinada que una la tabla Tiendas (tabla almacenada en el primer servidor) y la tabla Empleados (tabla almacenada en el segundo servidor):
SQL> SELECT Tiendas.Codigo AS Codigo, Tiendas.Nombre AS NombreTienda, Tiendas.Especialidad AS Especialidad, Tiendas.Localizacion AS Localizacion, Empleados.NIF AS NIF, Empleados.Nombre AS NombreEmpleado, Empleados.AnyoNacimiento AS AnyoNacimiento, Empleados.Cod_Tienda AS Cod_Tienda 2 FROM Tiendas, Empleados@linkserv2 Empleados 3 WHERE Tiendas.Codigo = Empleados.Cod_Tienda; CODIGO NOMBRETIENDA ESPECIALID LOCALIZACION ------ -------------------- ---------- ---------------------------------------- NIF --------- NOMBREEMPLEADO -------------------------------------------------------------------------------- ANYONACIMIENTO COD_TI -------------- ------ 000001 Javi s Pet Animales Sevilla 12345678A Rodrigo Fernandez 1974 000001 CODIGO NOMBRETIENDA ESPECIALID LOCALIZACION ------ -------------------- ---------- ---------------------------------------- NIF --------- NOMBREEMPLEADO -------------------------------------------------------------------------------- ANYONACIMIENTO COD_TI -------------- ------ 000002 Javi s Sport Deportes Cordoba 12345678B Cristina Perez 1976 000002 CODIGO NOMBRETIENDA ESPECIALID LOCALIZACION ------ -------------------- ---------- ---------------------------------------- NIF --------- NOMBREEMPLEADO -------------------------------------------------------------------------------- ANYONACIMIENTO COD_TI -------------- ------ 000003 Javi s Food Comida Granada 12345678C Ramon Fuentes 1983 000003 CODIGO NOMBRETIENDA ESPECIALID LOCALIZACION ------ -------------------- ---------- ---------------------------------------- NIF --------- NOMBREEMPLEADO -------------------------------------------------------------------------------- ANYONACIMIENTO COD_TI -------------- ------ 000004 Javi s Technology Tecnologia Cadiz 12345678D Maria Diaz 1969 000004 CODIGO NOMBRETIENDA ESPECIALID LOCALIZACION ------ -------------------- ---------- ---------------------------------------- NIF --------- NOMBREEMPLEADO -------------------------------------------------------------------------------- ANYONACIMIENTO COD_TI -------------- ------ 000005 Javi s Clothes Ropa Huelva 12345678E Alejandro Cortes 1978 000005
(El resultado de la consulta no tiene mucho sentido, pero lo importante es mostrar el funcionamiento).
Como hemos visto, hemos podido realizar la consulta correctamente, por lo que habríamos terminado este ejercicio.
Enlace entre dos servidores de bases de datos PostgreSQL
En este apartado vamos a realizar un enlace entre dos servidores PostgreSQL. Ambos servidores se encuentran instalados sobre Debian, aunque esto no es algo que influya en el proceso.
PostgreSQL hace uso de la extensión dblink
para realizar o aceptar consultas desde enlaces, por lo que debemos instalar esta herramienta que se encuentra en el paquete llamado postgresql-contrib
apt install postgresql-contrib -y
Hecho esto, procederemos a editar el fichero de configuración de ambos servidores /etc/postgresql/XXX/main/postgresql.conf
, y en él descomentaremos la línea llamada listen_addresses
. Como valor le estableceremos la IP que nos interese que escuche nuestro servidor, en mi caso introduzco el valor ***** para que así escuche cualquier petición. De manera que la línea resultante sería la siguiente:
listen_addresses = '*'
Como segunda modificación, que también debe realizarse en ambos servidores, tenemos que dirigirnos al fichero /etc/postgresql/XXX/main/pg_hba.conf
y buscar la siguiente línea:
host all all 127.0.0.1/32 md5
Esta línea actualmente define que no se permita la conexión remota, ya que por defecto solo escucha peticiones de localhost. Por tanto cambiamos este valor, en mi caso especifico que escuche peticiones desde cualquier interfaz, y la línea queda de esta manera:
host all all 0.0.0.0/0 md5
Realizados los cambios, vamos a reiniciar los servicios de los dos servidores para así aplicar los nuevos cambios:
systemctl restart postgresql
Ya tenemos ambos servidores configurados correctamente y tan solo nos faltaría crear el enlace desde el primer servidor al segundo, y al revés.
Para ello, antes, voy a crear en ambos servidores un usuario llamado javierservX, y una base de datos de prueba llamada empresaX, en la que introduciré algunos registros de prueba.
root@servidor:~# su - postgres postgres@servidor:~$ psql postgres psql (11.9 (Debian 11.9-0+deb10u1)) Type "help" for help. postgres=# CREATE USER javierserv1 WITH PASSWORD 'contraseña'; CREATE ROLE postgres=# CREATE DATABASE empresa1; CREATE DATABASE postgres=# GRANT ALL PRIVILEGES ON DATABASE empresa1 TO javierserv1; GRANT postgres=# exit -------------------------------------------------------------------------------- root@cliente:~# su - postgres postgres@cliente:~$ psql postgres psql (11.9 (Debian 11.9-0+deb10u1)) Type "help" for help. postgres=# CREATE USER javierserv2 WITH PASSWORD 'contraseña'; CREATE ROLE postgres=# CREATE DATABASE empresa2; CREATE DATABASE postgres=# GRANT ALL PRIVILEGES ON DATABASE empresa2 TO javierserv2; GRANT postgres=# exit
Una vez creados ambos usuarios y ambas bases de datos, inserto una serie de tablas con sus respectivos registros. Puedes encontrar la información aquí.
Hecho esto, llegó el momento de crear los enlaces entre ambos servidores. Los enlaces deben crearse con el usuario administrador postgres ya que es el usuario que posee los permisos para ello, y deben crearse en las bases de datos empresaX, ya que los usuarios javierservX, solo poseen permisos sobre ellas.
Explicado esto, en primer lugar, crearemos el enlace desde el primer servidor hacia el segundo:
postgres@servidor:~$ psql postgres psql (11.9 (Debian 11.9-0+deb10u1)) Type "help" for help. postgres=# \c empresa1 You are now connected to database "empresa1" as user "postgres". empresa1=# CREATE EXTENSION dblink; CREATE EXTENSION empresa1=# exit
Y ahora al revés, desde el segundo hacia el primero:
postgres@cliente:~$ psql postgres psql (11.9 (Debian 11.9-0+deb10u1)) Type "help" for help. postgres=# \c empresa2 You are now connected to database "empresa2" as user "postgres". empresa2=# CREATE EXTENSION dblink; CREATE EXTENSION empresa2=# exit
En principio ya estaría todo listo, así que vamos a probarlo. Empezaremos haciendo una consulta desde el servidor1 hacia el servidor2:
postgres@servidor:~$ psql -h 127.0.0.1 -U javierserv1 -d empresa1 Password for user javierserv1: psql (11.9 (Debian 11.9-0+deb10u1)) SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off) Type "help" for help. empresa1=> select * from dblink('dbname=empresa2 host=192.168.0.44 user=javierserv2 password=contraseña', 'select * from Empleados') AS Empleados (NIF VARCHAR, Nombre VARCHAR, AnyoNacimiento NUMERIC, Cod_Tienda VARCHAR); nif | nombre | anyonacimiento | cod_tienda -----------+-------------------+----------------+------------ 12345678A | Rodrigo Fernandez | 1974 | 000001 12345678B | Cristina Perez | 1976 | 000002 12345678C | Ramon Fuentes | 1983 | 000003 12345678D | Maria Diaz | 1969 | 000004 12345678E | Alejandro Cortes | 1978 | 000005 (5 rows)
Vemos que nos muestra la información correctamente. Pero, ¿y si quisiéramos unir una consulta de la tabla del primer servidor y de la tabla del segundo servidor? Pues vamos a ver si podríamos hacerlo:
postgres@servidor:~$ psql -h 127.0.0.1 -U javierserv1 -d empresa1 Password for user javierserv1: psql (11.9 (Debian 11.9-0+deb10u1)) SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off) Type "help" for help. empresa1=> select Tiendas.Codigo AS Codigo, Tiendas.Nombre AS NombreTienda, Tiendas.Especialidad AS Especialidad, Tiendas.Localizacion AS Localizacion, Empleados.NIF AS NIF, Empleados.Nombre AS NombreEmpleado, Empleados.AnyoNacimiento AS AnyoNacimiento, Empleados.Cod_Tienda AS Cod_Tienda empresa1-> from Tiendas, dblink('dbname=empresa2 host=192.168.0.44 user=javierserv2 password=contraseña', 'select * from Empleados') AS Empleados (NIF VARCHAR, Nombre VARCHAR, AnyoNacimiento NUMERIC, Cod_Tienda VARCHAR) empresa1-> where Tiendas.Codigo=Empleados.Cod_Tienda; codigo | nombretienda | especialidad | localizacion | nif | nombreempleado | anyonacimiento | cod_tienda --------+-------------------+--------------+--------------+-----------+-------------------+----------------+------------ 000001 | Javi s Pet | Animales | Sevilla | 12345678A | Rodrigo Fernandez | 1974 | 000001 000002 | Javi s Sport | Deportes | Cordoba | 12345678B | Cristina Perez | 1976 | 000002 000003 | Javi s Food | Comida | Granada | 12345678C | Ramon Fuentes | 1983 | 000003 000004 | Javi s Technology | Tecnologia | Cadiz | 12345678D | Maria Diaz | 1969 | 000004 000005 | Javi s Clothes | Ropa | Huelva | 12345678E | Alejandro Cortes | 1978 | 000005 (5 rows)
Efectivamente podemos unir ambas consultas, ¡esto es maravilloso!
(El resultado de la consulta no tiene mucho sentido, pero lo importante es mostrar el funcionamiento).
Para terminar con este apartado, haremos la misma consulta pero esta vez desde el segundo servidor, y de esta manera asegurarnos que ambos enlaces funcionan.
postgres@cliente:~$ psql -h 127.0.0.1 -U javierserv2 -d empresa2 Password for user javierserv2: psql (11.9 (Debian 11.9-0+deb10u1)) SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off) Type "help" for help. empresa2=> select Tiendas.Codigo AS Codigo, Tiendas.Nombre AS NombreTienda, Tiendas.Especialidad AS Especialidad, Tiendas.Localizacion AS Localizacion, Empleados.NIF AS NIF, Empleados.Nombre AS NombreEmpleado, Empleados.AnyoNacimiento AS AnyoNacimiento, Empleados.Cod_Tienda AS Cod_Tienda empresa2-> from Empleados, dblink('dbname=empresa1 host=192.168.0.43 user=javierserv1 password=contraseña', 'select * from Tiendas') AS Tiendas (Codigo VARCHAR, Nombre VARCHAR, Especialidad VARCHAR, Localizacion VARCHAR) empresa2-> where Empleados.Cod_Tienda=Tiendas.Codigo; codigo | nombretienda | especialidad | localizacion | nif | nombreempleado | anyonacimiento | cod_tienda --------+-------------------+--------------+--------------+-----------+-------------------+----------------+------------ 000001 | Javi s Pet | Animales | Sevilla | 12345678A | Rodrigo Fernandez | 1974 | 000001 000002 | Javi s Sport | Deportes | Cordoba | 12345678B | Cristina Perez | 1976 | 000002 000003 | Javi s Food | Comida | Granada | 12345678C | Ramon Fuentes | 1983 | 000003 000004 | Javi s Technology | Tecnologia | Cadiz | 12345678D | Maria Diaz | 1969 | 000004 000005 | Javi s Clothes | Ropa | Huelva | 12345678E | Alejandro Cortes | 1978 | 000005 (5 rows)
Lógicamente funciona igualmente, por lo que este apartado habría terminado.
Enlace entre un servidor ORACLE y un servidor PostgreSQL empleando Heterogeneus Services
En este último caso, vamos a enlazar un servidor Oracle y otro PostgreSQL. El servidor Oracle se encuentra instalado sobre un sistema CentOS y el servidor PostgreSQL, sobre Debian (es el que he utilizado en el apartado anterior), aunque esto no es algo que influya en el proceso.
Algo importante es que, ambos servidores ya están configurados previamente y permiten conexiones remotas.
ORACLE a PostgreSQL
Nos situamos en la máquina que contiene el servidor Oracle.
El primer paso que debemos realizar consiste en instalar el paquete unixODBC
, que contiene el software necesario para crear dicho enlace, y junto a él, el driver específico llamado postgresql-odbc
:
[root@servidororacle ~]# dnf install unixODBC postgresql-odbc -y
Una vez instalados, procederemos a visualizar el fichero de configuración /etc/odbcinst.ini
. En él podremos apreciar todos los drivers existentes, pero en nuestra caso nos interesa el que hace referencia a PostgreSQL.
El próximo paso consiste en la creación del fichero /etc/odbc.ini
, ya que dicho fichero será el utilizado para determinar la manera de conectarse al servidor PostgreSQL. En él introduciremos el siguiente contenido:
[PSQLU] Debug = 0 CommLog = 0 ReadOnly = 0 Driver = PostgreSQL Servername = 192.168.0.43 Username = javierserv1 Password = contraseña Port = 5432 Database = empresa1 Trace = 0 TraceFile = /tmp/sql.log
Las informaciones como pueden ser Servername, Username, Password, Port y Database, hacen referencia al servidor al que nos vamos a conectar, por lo que debemos introducir nuestros datos de PostgreSQL.
Creado este fichero, habríamos terminado la configuración del driver de ODBC. Para comprobar que el funcionamiento es el correcto, podemos hacer uso del comando isql
, como vemos a continuación:
[root@servidororacle ~]# isql PSQLU +---------------------------------------+ | Connected! | | | | sql-statement | | help [tablename] | | quit | | | +---------------------------------------+ SQL>
Vemos como se nos abre una especie de cliente en el que podemos ejecutar órdenes SQL:
SQL> select * from empleados; +----------+-------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+-----------+ | nif | nombre | anyonacimiento| cod_tienda| +----------+-------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+-----------+ | 12345678A| Rodrigo Fernandez | 1974 | 000001 | | 12345678B| Cristina Perez | 1976 | 000002 | | 12345678C| Ramon Fuentes | 1983 | 000003 | | 12345678D| Maria Diaz | 1969 | 000004 | | 12345678E| Alejandro Cortes | 1978 | 000005 | +----------+-------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+-----------+ SQLRowCount returns 5 5 rows fetched
Parece que la conexión hacia el servidor PostgreSQL es correcta, así que ahora sería el turno de configurar Oracle para utilizar este driver.
Para ello debemos crear el fichero initPSQLU.ora
, en el que tendremos que especificar los parámetros que veremos a continuación. Este fichero debemos crearlo en la ruta /opt/oracle/product/19c/dbhome_1/hs/admin/initPSQLU.ora
y su contenido sería el siguiente:
HS_FDS_CONNECT_INFO = PSQLU HS_FDS_TRACE_LEVEL = DEBUG HS_FDS_SHAREABLE_NAME = /usr/lib64/psqlodbcw.so HS_LANGUAGE = AMERICAN_AMERICA.WE8ISO8859P1 set ODBCINI=/etc/odbc.ini
Podemos apreciar que hemos definido varios parámetros que hacen referencia al driver configurado anteriormente, al fichero que define la conexión con PostgreSQL, …
Tras ello, ya estaría todo listo para dirigirnos a los ficheros listener.ora
y tnsnames.ora
, ambos se encuentran en la ruta /opt/oracle/product/19c/dbhome_1/network/admin/
, y en ellos es donde realizaremos las siguientes configuraciones.
Primeramente, debemos modificar el fichero listener.ora
y añadir la siguiente entrada:
SID_LIST_LISTENER= (SID_LIST= (SID_DESC= (SID_NAME=PSQLU) (ORACLE_HOME=/opt/oracle/product/19c/dbhome_1) (PROGRAM=dg4odbc) ) )
Hecho esto, vamos a dirigirnos al segundo y último fichero de configuración, el llamado tnsnames.ora
, que por defecto posee esta configuración:
ORCLCDB = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = servidororacle)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = ORCLCDB) ) ) LISTENER_ORCLCDB = (ADDRESS = (PROTOCOL = TCP)(HOST = servidororacle)(PORT = 1521))
Añadiremos este último bloque:
PSQLU = (DESCRIPTION= (ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521)) (CONNECT_DATA=(SID=PSQLU)) (HS=OK) )
Una vez hemos realizado todos los cambios, podemos iniciar el listener. El listener se maneja con estos comandos:
- lsnrctl start: inicia el servicio.
- lsnrctl stop: detiene el servicio.
- lsnrctl status: muestra información sobre el estado.
Lo iniciamos:
[oracle@servidororacle ~]$ lsnrctl start LSNRCTL for Linux: Version 19.0.0.0.0 - Production on 18-FEB-2021 20:35:40 Copyright (c) 1991, 2019, Oracle. All rights reserved. Starting /opt/oracle/product/19c/dbhome_1/bin/tnslsnr: please wait... TNSLSNR for Linux: Version 19.0.0.0.0 - Production System parameter file is /opt/oracle/product/19c/dbhome_1/network/admin/listener.ora Log messages written to /opt/oracle/diag/tnslsnr/servidororacle/listener/alert/log.xml Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=servidororacle)(PORT=1521))) Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521))) Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=servidororacle)(PORT=1521))) STATUS of the LISTENER ------------------------ Alias LISTENER Version TNSLSNR for Linux: Version 19.0.0.0.0 - Production Start Date 18-FEB-2021 20:35:40 Uptime 0 days 0 hr. 0 min. 0 sec Trace Level off Security ON: Local OS Authentication SNMP OFF Listener Parameter File /opt/oracle/product/19c/dbhome_1/network/admin/listener.ora Listener Log File /opt/oracle/diag/tnslsnr/servidororacle/listener/alert/log.xml Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=servidororacle)(PORT=1521))) (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521))) Services Summary... Service "PSQLU" has 1 instance(s). Instance "PSQLU", status UNKNOWN, has 1 handler(s) for this service... The command completed successfully
Vemos que lo ha iniciado correctamente.
Cuando ya poseemos todas las configuraciones listas, procederemos a crear la conexión entre los servidores.
Pero antes de esto, voy a crear un usuario:
[oracle@servidororacle ~]$ sqlplus / as sysdba SQL*Plus: Release 19.0.0.0.0 - Production on Thu Feb 18 19:39:08 2021 Version 19.3.0.0.0 Copyright (c) 1982, 2019, Oracle. All rights reserved. Conectado a: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production Version 19.3.0.0.0 SQL> CREATE USER c##javier1 IDENTIFIED BY contraseña; Usuario creado. SQL> GRANT ALL PRIVILEGES TO c##javier1; Concesion terminada correctamente.
Ahora sí, vamos a crear el propio enlace.
Para ello accederemos con el nuevo usuario c##javier1 y crearemos el enlace hacia el servidor PostgreSQL.
La sintaxis para crear un enlace es la siguiente:
create database link linkservpostgresql connect to "javierserv1" identified by "contraseña" using 'PSQLU';
NOTA: Es importante utilizar comillas dobles para el nombre de usuario y la contraseña, y comillas simples para el nombre del alias.
El usuario y la contraseña hacen referencia a las credenciales de la base de datos remota.
Vemos el resultado de la creación del enlace:
[oracle@servidororacle ~]$ sqlplus c##javier1 SQL*Plus: Release 19.0.0.0.0 - Production on Thu Feb 18 20:42:15 2021 Version 19.3.0.0.0 Copyright (c) 1982, 2019, Oracle. All rights reserved. Enter password: Hora de Ultima Conexion Correcta: Jue Feb 18 2021 20:38:21 +01:00 Conectado a: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production Version 19.3.0.0.0 SQL> create database link linkservpostgresql 2 connect to "javierserv1" 3 identified by "contraseña" 4 using 'PSQLU'; Enlace con la base de datos creado.
Con esto, habríamos terminado la creación del enlace.
Vamos a probarlo haciendo una consulta sencilla:
SQL> select "nombre" from "empleados"@linkservpostgresql; nombre -------------------------------------------------------------------------------- Rodrigo Fernandez Cristina Perez Ramon Fuentes Maria Diaz Alejandro Cortes
Obviamente, gracias a este enlace también podremos realizar consultas combinadas, es decir, que incluyan informaciones de ambos servidores, vamos a verlo haciendo una consulta a la tabla Tiendas(tabla almacenada en el primer servidor) y la tabla Empleados (tabla almacenada en el segundo servidor):
SQL> SELECT Tiendas.Codigo AS Codigo, Tiendas.Nombre AS NombreTienda, Tiendas.Especialidad AS Especialidad, Tiendas.Localizacion AS Localizacion, Empleados."nif" AS NIF, Empleados."nombre" AS NombreEmpleado, Empleados."anyonacimiento" AS AnyoNacimiento, Empleados."cod_tienda" AS Cod_Tienda 2 FROM Tiendas, "empleados"@linkservpostgresql Empleados 3 WHERE Tiendas.Codigo = Empleados."cod_tienda"; CODIGO NOMBRETIENDA ESPECIALID LOCALIZACION ------ -------------------- ---------- ---------------------------------------- NIF -------------------------------------------------------------------------------- NOMBREEMPLEADO -------------------------------------------------------------------------------- ANYONACIMIENTO -------------- COD_TIENDA ------------------------------------------------------------------------ 000001 Javi s Pet Animales Sevilla 12345678A Rodrigo Fernandez CODIGO NOMBRETIENDA ESPECIALID LOCALIZACION ------ -------------------- ---------- ---------------------------------------- NIF -------------------------------------------------------------------------------- NOMBREEMPLEADO -------------------------------------------------------------------------------- ANYONACIMIENTO -------------- COD_TIENDA ------------------------------------------------------------------------ 1974 000001 CODIGO NOMBRETIENDA ESPECIALID LOCALIZACION ------ -------------------- ---------- ---------------------------------------- NIF -------------------------------------------------------------------------------- NOMBREEMPLEADO -------------------------------------------------------------------------------- ANYONACIMIENTO -------------- COD_TIENDA ------------------------------------------------------------------------ 000002 Javi s Sport Deportes Cordoba 12345678B Cristina Perez CODIGO NOMBRETIENDA ESPECIALID LOCALIZACION ------ -------------------- ---------- ---------------------------------------- NIF -------------------------------------------------------------------------------- NOMBREEMPLEADO -------------------------------------------------------------------------------- ANYONACIMIENTO -------------- COD_TIENDA ------------------------------------------------------------------------ 1976 000002 CODIGO NOMBRETIENDA ESPECIALID LOCALIZACION ------ -------------------- ---------- ---------------------------------------- NIF -------------------------------------------------------------------------------- NOMBREEMPLEADO -------------------------------------------------------------------------------- ANYONACIMIENTO -------------- COD_TIENDA ------------------------------------------------------------------------ 000003 Javi s Food Comida Granada 12345678C Ramon Fuentes CODIGO NOMBRETIENDA ESPECIALID LOCALIZACION ------ -------------------- ---------- ---------------------------------------- NIF -------------------------------------------------------------------------------- NOMBREEMPLEADO -------------------------------------------------------------------------------- ANYONACIMIENTO -------------- COD_TIENDA ------------------------------------------------------------------------ 1983 000003 CODIGO NOMBRETIENDA ESPECIALID LOCALIZACION ------ -------------------- ---------- ---------------------------------------- NIF -------------------------------------------------------------------------------- NOMBREEMPLEADO -------------------------------------------------------------------------------- ANYONACIMIENTO -------------- COD_TIENDA ------------------------------------------------------------------------ 000004 Javi s Technology Tecnologia Cadiz 12345678D Maria Diaz CODIGO NOMBRETIENDA ESPECIALID LOCALIZACION ------ -------------------- ---------- ---------------------------------------- NIF -------------------------------------------------------------------------------- NOMBREEMPLEADO -------------------------------------------------------------------------------- ANYONACIMIENTO -------------- COD_TIENDA ------------------------------------------------------------------------ 1969 000004 CODIGO NOMBRETIENDA ESPECIALID LOCALIZACION ------ -------------------- ---------- ---------------------------------------- NIF -------------------------------------------------------------------------------- NOMBREEMPLEADO -------------------------------------------------------------------------------- ANYONACIMIENTO -------------- COD_TIENDA ------------------------------------------------------------------------ 000005 Javi s Clothes Ropa Huelva 12345678E Alejandro Cortes CODIGO NOMBRETIENDA ESPECIALID LOCALIZACION ------ -------------------- ---------- ---------------------------------------- NIF -------------------------------------------------------------------------------- NOMBREEMPLEADO -------------------------------------------------------------------------------- ANYONACIMIENTO -------------- COD_TIENDA ------------------------------------------------------------------------ 1978 000005
(El resultado de la consulta no tiene mucho sentido, pero lo importante es mostrar el funcionamiento).
Podemos apreciar como efectivamente podemos realizar la consulta correctamente.
PostgreSQL a ORACLE
Nos situamos en la máquina que contiene el servidor PostgreSQL.
El primer paso que debemos realizar consiste en la instalación de un Data Wrappers, pero, ¿qué son estos Data Wrappers? Pues son una especie de extensiones que permiten conectar servidores PostgreSQL con otros gestores de bases de datos, como pueden ser Oracle, MySQL o MongoDB. En el caso de Oracle, que es el que nos interesa, podemos recurrir al paquete oracle_fdw
.
.