El objetivo de este post es el de mostrar el procedimiento a seguir para llevar a cabo una interconexión entre dos servidores Oracle 19c alojados en máquinas CentOS 8, siendo su finalidad la de permitir el acceso desde un mismo cliente a dos bases de datos de forma simultánea pero indirecta, por ejemplo, para hacer un JOIN con tablas que se encuentren en distintos servidores mediante un enlace entre ellas, de manera que uno de los servidores actuará como cliente del otro servidor, de manera unidireccional.
Al fin y al cabo, el cliente únicamente abre una conexión, pues es el primer servidor al que se conecta el que posteriormente abre una conexión al segundo de ellos.
Para esta ocasión, he traído los deberes hechos y he instalado previamente dos máquinas virtuales con CentOS 8, a las que he instalado a su vez el gestor de bases de datos Oracle 19c, siguiendo para ello los pasos indicados con mayor detenimiento en el artículo Instalación de Oracle 19c en CentOS 8. Las máquinas actualmente existentes en el escenario son las siguientes:
- oracle1: Conectada a mi red doméstica en modo puente (bridge), con dirección IP asignada 192.168.1.150.
- oracle2: Conectada a mi red doméstica en modo puente (bridge), con dirección IP asignada 192.168.1.151.
Además de la instalación, he llevado a cabo sobre ambos servidores las configuraciones necesarias para montar las bases de datos, así como permitir conexiones remotas, estableciendo para ello el correspondiente FQDN a la máquina y editando el listener.ora, además de levantar, como es lógico, el listener. Si los pasos seguidos no han quedado claros, se pueden encontrar de forma más detallada en el artículo anteriormente mencionado.
Cuando la configuración inicial haya sido correctamente realizada en ambas máquinas servidoras, procederemos a abrir una shell de sqlplus en la primera de ellas para así poder gestionar el motor, cambiándonos previamente al usuario oracle, pues es el único que tiene actualmente definida en sus variables de entorno la ruta a los binarios de Oracle, ejecutando por tanto el comando:
Cuando nos encontremos haciendo uso del usuario oracle, todo estará listo para abrir la shell de sqlplus utilizando el usuario sysdba, pues es el que cuenta con los privilegios necesarios para llevar a cabo determinadas acciones, haciendo para ello uso del comando:
Como se puede apreciar, la sqlplus shell se ha abierto correctamente y está lista para su uso.
Para hacer un artículo un poco más completo, vamos a proceder a simular una situación real, en la que se tuviese que definir un nuevo usuario (schema) que pueda hacer uso tanto de la CDB actual como de futuras PDBs que se creen. En este caso, voy a crear un usuario común (common user) de nombre “c##alvaro1” y cuya contraseña sea también “alvaro1” (lógicamente, en un caso real se usarían credenciales más seguras). Para ello, haremos uso de la instrucción:
Cuando el usuario haya sido generado, lo dotaremos de todos los privilegios para poder trabajar con el mismo sin ningún tipo de restricción (es importante mencionar que en una situación real habría que hacer una gestión de permisos de forma granular y específica para que no suponga un agujero de seguridad en la base de datos), ejecutando para ello el comando:
Ya hemos finalizado con la creación y configuración de privilegios para el nuevo usuario, así que el siguiente paso será desconectarnos del usuario actual (sysdba), haciendo uso de la instrucción:
Tras ello, trataremos de acceder al nuevo usuario creado, indicando seguidamente su contraseña (o bien, indicando únicamente el nombre de usuario, de manera que la contraseña se pedirá por teclado de forma oculta):
Como se puede apreciar, la conexión al nuevo usuario se ha realizado exitosamente, por lo que he procedido a crear algunas tablas e insertar una serie de registros. Para no ensuciar el artículo con la inserción de tablas y registros, se podrá encontrar aquí las instrucciones ejecutadas para ello.
Una vez insertadas las correspondientes tablas y registros, saldremos del cliente ejecutando la instrucción exit
para así visualizar las interfaces de red existentes en la máquina junto con sus direcciones IP asignadas, pues nos será necesario conocer dicha información para la correspondiente conexión remota, haciendo para ello uso del comando ip a
:
De las cuatro interfaces mostradas, la única que nos interesa es aquella de nombre enp0s3, que tiene un direccionamiento 192.168.1.150/24, resultante de estar conectada a mi red doméstica en modo puente (bridge).
Resumiendo, tenemos un servicio que está actualmente escuchando peticiones en todas las interfaces de la máquina (0.0.0.0) en el puerto 1521. Además, hemos configurado un usuario c##alvaro1 que cuenta con los permisos necesarios para hacer uso de la base de datos.
De otro lado, tendremos que repetir en la máquina servidora oracle2 el mismo procedimiento seguido en la máquina oracle1, con la única diferencia de que el usuario a generar será ahora c##alvaro2, para así poder diferenciarlo del anterior.
Resumiendo una vez más, tenemos un servicio que está actualmente escuchando peticiones en todas las interfaces de la máquina (0.0.0.0) en el puerto 1521. Además, hemos configurado un usuario c##alvaro2 que cuenta con los permisos necesarios para hacer uso de la base de datos.
Ambas máquinas servidoras se encuentran ya totalmente configuradas, de manera que todo está listo para interconectarlas. Para ello, realizaremos el procedimiento de forma ordenada, configurando primero el enlace de la máquina oracle1 a la máquina oracle2 y posteriormente, a la inversa, ya que dichas conexiones son unidireccionales.
Lo primero que haremos será comprobar la conectividad a la máquina oracle2, pero no una conectividad normal y corriente como la que nos podría ofrecer el comando ping
, sino conectividad con el listener de Oracle, para así confirmar que tenemos acceso al puerto 1521. Para ello, haremos uso de tnsping
, indicando a su vez la dirección IP de la máquina a la que nos queremos conectar (en este caso, 192.168.1.151):
Como se puede apreciar en la última línea de la salida del comando, el intento de conexión con el listener ha sido exitoso en un tiempo total de 0 ms, pues ambas máquinas virtuales están ubicadas en la misma máquina física, por lo que el tiempo de transferencia es ridículamente minúsculo.
El siguiente paso será modificar el fichero de nombre tnsnames.ora, ubicado en $ORACLE_HOME/network/admin/, que permite facilitar la tarea de acceso a servidores remotos, indicando en el mismo una entrada por cada uno de los servidores a los que se pretende acceder.
Dichas entradas contienen a su vez el protocolo, la dirección IP y el puerto, así como un alias que será el que se utilice a la hora de la conexión a un determinado servidor. Su configuración no es para nada complicada, así que vamos a llevarla a cabo ejecutando para ello el comando:
El contenido que encontraremos por defecto dentro de dicho fichero es el siguiente:
Dentro del mismo, tendremos que definir un nuevo alias para la máquina a la que pretendemos conectarnos, en este caso, para oracle2. El nombre del mismo no influye, de manera que en mi caso lo llamaré ORACLE2. El protocolo de conexión será TCP a la dirección 192.168.1.151, utilizando el puerto por defecto, 1521. Por último, tendremos que indicar el nombre del servicio/base de datos al que queremos conectarnos, que por defecto será ORCLCDB. El resultado final sería:
Una vez modificado el fichero tnsnames.ora, tendremos que cambiarnos una vez más al usuario oracle para utilizar el binario sqlplus, haciendo para ello uso del comando:
Cuando nos encontremos utilizando el usuario oracle, todo estará listo para abrir la shell de sqlplus haciendo uso del usuario c##alvaro1, ejecutando para ello el comando:
La creación del enlace será muy sencilla, ya que previamente hemos definido los parámetros de la conexión en el fichero tnsnames.ora, llevándose a cabo mediante la ejecución del comando:
Donde:
- CREATE DATABASE LINK: Especificamos un nombre identificativo para el enlace.
- CONNECT TO: Indicamos las credenciales de acceso a la base de datos remota.
- USING: Indicamos el nombre del alias de la conexión que previamente hemos definido en el fichero tnsnames.ora.
Efectivamente, el enlace oracle2link ha sido correctamente generado, de manera que vamos a proceder a verificar el funcionamiento de dicho enlace, ejecutando para ello una consulta cuya información mostrada provenga de ambas bases de datos, ubicadas como ya hemos visto, en servidores distintos.
La intención es mostrar los datos de los Empleados (tabla que se encuentra en oracle1) junto al nombre del departamento al que pertenecen, información que podremos obtener de Departamentos (tabla que se encuentra en oracle2), utilizando para ello la clave que tienen en común ambas tablas. La consulta a ejecutar sería:
Donde:
- SELECT: Indicamos las columnas que queremos mostrar de la información obtenida, de la forma [tabla].[columna].
- FROM: Hacemos un JOIN de la tabla Empleados que se encuentra en la base de datos local junto a la consulta remota, haciendo uso del enlace que acabamos de generar, para así poder mostrar información de ambas tablas en la misma consulta.
- WHERE: Establecemos la condición del JOIN, que deberá ser aquella columna mediante la cual vamos a unir los registros devueltos. Como es lógico, será el código del departamento, pues es la columna que se repite en ambas tablas.
Al parecer, la consulta se ha realizado sin ningún problema y ha devuelto la información que debería, pues tal y como he mencionado con anterioridad, ambas máquinas servidoras cuentan con un direccionamiento dentro de la red local, siendo ambas totalmente alcanzables entre sí, además de estar correctamente configuradas para aceptar dichas conexiones.
Otra utilidad que estos enlaces nos aportan es la capacidad de copiar las tablas de un gestor a otro, utilizando el resultado de una consulta simple para crear una tabla a partir de la misma. Por ejemplo, podríamos copiar la tabla Departamentos haciendo uso de la siguiente instrucción:
En dicha instrucción, hemos realizado una consulta a la tabla Departamentos ubicada en la base de datos del servidor oracle2, utilizando la respuesta obtenida para crear una nueva tabla con el mismo nombre, que se almacenará ahora de forma local en el servidor oracle1, y que podremos empezar a utilizar sin necesidad de recurrir al enlace con el segundo servidor. Si consultamos la nueva tabla generada, obtendremos el siguiente resultado:
Como se puede apreciar, el contenido es exactamente el mismo que el existente en la tabla ubicada en el gestor remoto, por lo que podemos concluir que su clonación ha sido efectiva.
El enlace ha funcionado del extremo oracle1 al extremo oracle2, pero como ya sabemos, dichos enlaces son unidireccionales, de manera que si quisiésemos realizar la conexión a la inversa, tendríamos que repetir el mismo procedimiento en la segunda máquina, así que vamos a proceder a ello.
Una vez más, tendremos que comprobar la conectividad con el listener de la máquina oracle1, haciendo uso de tnsping
, indicando a su vez la dirección IP de la máquina a la que nos queremos conectar (en este caso, 192.168.1.150):
Como era de esperar, el intento de conexión con el listener ha sido exitoso una vez más en un tiempo total de 0 ms.
El siguiente paso será modificar el fichero de nombre tnsnames.ora, ubicado en $ORACLE_HOME/network/admin/, indicando en el mismo una entrada para el nuevo servidor al que se pretende acceder, ejecutando para ello el comando:
Dentro del mismo, tendremos que definir un nuevo alias para la máquina a la que pretendemos conectarnos, en este caso, para oracle1. El nombre del mismo no influye, de manera que en mi caso lo llamaré ORACLE1. El protocolo de conexión será TCP a la dirección 192.168.1.150, utilizando el puerto por defecto, 1521. Por último, tendremos que indicar el nombre del servicio/base de datos al que queremos conectarnos, que por defecto será ORCLCDB. El resultado final sería:
Una vez modificado el fichero tnsnames.ora, tendremos que cambiarnos una vez más al usuario oracle para utilizar el binario sqlplus, haciendo para ello uso del comando:
Cuando nos encontremos utilizando el usuario oracle, todo estará listo para abrir la shell de sqlplus haciendo uso del usuario c##alvaro2, ejecutando para ello el comando:
La creación del enlace será muy sencilla, ya que previamente hemos definido los parámetros de la conexión en el fichero tnsnames.ora, llevándose a cabo mediante la ejecución del comando:
Efectivamente, el enlace oracle1link ha sido correctamente generado, de manera que vamos a proceder a verificar el funcionamiento de dicho enlace, ejecutando para ello una consulta cuya información mostrada provenga de ambas bases de datos, ubicadas como ya hemos visto, en servidores distintos.
La intención es realizar la misma consulta que en el caso anterior, pero adaptándola para consultar al primero de los servidores sobre la información de la tabla Empleados, ya que la tabla Departamentos se encuentra ahora en la máquina local. La consulta a ejecutar sería:
Como era de esperar, la consulta ha vuelto a realizarse sin ningún problema y ha devuelto la información que debería, de manera que vamos a hacer una última prueba, llevando a cabo una copia de la tabla Empleados ubicada en el primero de los servidores, haciendo uso de la siguiente instrucción:
En dicha instrucción, hemos realizado una consulta a la tabla Empleados ubicada en la base de datos del servidor oracle1, utilizando la respuesta obtenida para crear una nueva tabla con el mismo nombre, que se almacenará ahora de forma local en el servidor oracle2, y que podremos empezar a utilizar sin necesidad de recurrir al enlace con el primer servidor. Si consultamos la nueva tabla generada, obtendremos el siguiente resultado:
Como se puede apreciar, el contenido es exactamente el mismo que el existente en la tabla ubicada en el gestor remoto, por lo que podemos concluir que su clonación ha sido efectiva y que los servidores tienen conectividad entre sí mediante los enlaces creados, sea cual sea el sentido utilizado.