Interconexión de Servidores de Bases de Datos
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 esta entrada veremos varias formas de crear un enlace entre distintos servidores de bases de datos.
Interconexión entre dos BBDD Oracle
Entorno Vagrant
Tenemos 2 máquinas Centos con Oracle 11g XE levantadas mediante Vagrant y VirtualBox. Una la utiliaremos como "servidor" para la interconexión de datos y otra como "cliente".
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 | Vagrant.configure("2") do |config|
config.vm.define "nodo1" do |nodo1|
config.vm.provider "virtualbox" do |vb|
vb.name = "oracle1"
vb.memory = 2048
vb.cpus = 1
end
nodo1.vm.box = "neko-neko/centos6-oracle-11g-XE"
nodo1.vm.hostname = "oracle1"
nodo1.vm.network "public_network",
bridge: "wlan0",
use_dhcp_assigned_default_route: true
end
config.vm.define "nodo2" do |nodo2|
config.vm.provider "virtualbox" do |vb|
vb.name = "oracle2"
vb.memory = 2048
vb.cpus = 1
end
nodo2.vm.box = "neko-neko/centos6-oracle-11g-XE"
nodo2.vm.hostname = "oracle2"
nodo2.vm.network "public_network",
bridge: "wlan0",
use_dhcp_assigned_default_route: true
end
end
|
Mi red es una 192.168.1.0
.
- Acciones iniciales en la máquina:
1
2
3
4
5
6
7
8
9
10
11
12
13 | sudo su -
yum -y update
yum -y install nano rlwrap
sed -ri 's/NLS_LANG=.*/NLS_LANG="SPANISH_SPAIN.AL32UTF8"/g' /etc/profile.d/oracle_env.sh
export NLS_LANG='SPANISH_SPAIN.AL32UTF8'
rlwrap sqlplus sys/vagrant as sysdba
cat <<EOF>>$ORACLE_HOME/sqlplus/admin/glogin.sql
alter session set NLS_DATE_FORMAT = 'DD-MM-YYYY HH24:mi:ss';
set sqlprompt "_DATE _USER'@'_CONNECT_IDENTIFIER 'SQL'> "
set pagesize 2000 linesize 100
set serveroutput on
EOF
|
Fichero listener.ora
en "servidor"
Este apartado es para el servidor de escucha.
Lo primero será modificar el fichero de configuración listener.ora
. En este fichero podremos configurar el interlocutor de oracle(listener) el cual se encarga de aceptar peticiones remotas desde la red(TCP). Lo encontraremos en el directorio $ORACLE_HOME/network/admin
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
)
)
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = XE)
(GLOBAL_DBNAME = XE)
(ORACLE_HOME = /u01/app/oracle/product/11.2.0/xe)
)
)
DEFAULT_SERVICE_LISTENER = (XE)
|
-
LISTENER:
Es dónde especificamos los protocolos,IPs o nombres(HOST), puertos y etc. desde los que se podrán conectar remotamente a este servidor.
Al especificar "localhost", se podrá conectar cualquiera que tenga acceso a la red de la máquina. Si por ejemplo usaramos en vez de "localhost" usaramos "192.168.1.31", sólo podrán acceder los que tengan acceso a la red "192.168.1.0/24".
-
SID_LIST_LISTENER:
Son los nombres de los servicios de escucha dónde especificamos los nombres de las instancias y directorio de las bases de datos. (SID_NAME,GLOBAL_DBNAME,ORACLE_HOME)
-
DEFAULT_SERVICE_LISTENER:
Por defecto el servicio de escucha se llama "XE".

- Ahora reiniciamos el servicio del listener:
| lsnrctl stop && lsnrctl start
|
- Vemos el estado del listener:

- Para averiguar el
SID_NAME
, GLOBAL_DBNAME
y el nombre del servidor:
| SELECT SYS_CONTEXT('USERENV','INSTANCE_NAME') FROM dual;
SELECT * FROM global_name;
SELECT SYS_CONTEXT('USERENV', 'SERVER_HOST') FROM dual;
|

¿ Qué es el SID_NAME
?
Identificador del Sistema Oracle: Es un nombre único para una instancia de Oracle Database en un host concreto. El identificador del sistema Oracle (SID) ayuda a identificar el archivo de control así como a ubicar los archivos necesarios para abrir la base de datos. Suele ser el mismo que el del GLOBAL_DBNAME
.
Fichero tnsnames.ora
en "cliente"
Este apartado es para el cliente desde el cual nos conectaremos.
Primero realizaremos varias pruebas para verificar que tenemos conexión con el servidor de escucha.

Como vemos el primer intento a 192.168.1.31
(Servidor de escucha) tiene éxito, pero intentamos realizar esta operación a una IP inexistente y da error.
- Pruebas de conexión con
sqlplus
:
| rlwrap sqlplus system/vagrant@//192.168.1.31:1521/XE
|

Podemos ver que estamos conectado al servidor de escucha con nombre "oracle1".
Ahora para realizar la interconexión del servidor necesitamos configurar el fichero tnsnames.ora
. En este fichero podemos configurar y "mapear" los nombres de los servicios que está escuchando el servidor. Lo encontraremos en el directorio $ORACLE_HOME/network/admin
.
| tns_ora1 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.31)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = XE)
)
)
|
- ADDRESS:
Especificamos el protocolo, IP o nombre y puerto de la máquina a la que queremos conectarnos.
- SERVICE_NAME:
Nombre del servicio de la base de datos a la que nos conectaremos.

- Volvemos a realizar una prueba con
tnsping
pero esta vez usando el nombre especificado:

Como vemos el primer intento a "tns_ora1"(Servidor de escucha) tiene éxito, pero intentamos realizar esta operación a un nombre no configurado y da error.
Ahora necesitamos configurar dicho enlace en el cliente desde "sqlplus".
| CREATE DATABASE LINK link_ora1
CONNECT TO scott
IDENTIFIED BY tiger
USING 'tns_ora1';
|
-
LINK:
Nombre que llamaremos al enlace de base dedatos para luego utilizarlo en las consultas, etc..
-
CONNECT TO:
Usuario con el que nos conectaremos a la base de datos de "oracle1"
-
USING:
Nombre del "mapeo" establecido en tnsnames.ora
.
- Consulta a la base de datos de "oracle1" desde "oracle2":
| SELECT *
FROM scott.emp@link_ora1;
|

Interconexión entre dos BBDD Postgres
Escenario vagrant
Ya que el escenario anterior eran de máquinas Centos 6 (2016), ahora utilizaremos otro escenario con máquinas Debian Stretch para la interconexión de 2 base de datos postgres.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 | Vagrant.configure("2") do |config|
config.vm.define "nodo3" do |nodo3|
config.vm.provider "virtualbox" do |vb|
vb.name = "postres1"
vb.cpus = 1
end
nodo3.vm.box = "debian/stretch64"
nodo3.vm.hostname = "postgres1"
nodo3.vm.network "public_network",
bridge: "wlan0",
use_dhcp_assigned_default_route: true
end
config.vm.define "nodo4" do |nodo4|
config.vm.provider "virtualbox" do |vb|
vb.name = "postres2"
vb.cpus = 1
end
nodo4.vm.box = "debian/stretch64"
nodo4.vm.hostname = "postres2"
nodo4.vm.network "public_network",
bridge: "wlan0",
use_dhcp_assigned_default_route: true
end
end
|
Instalación y configuración de Postgres para acceso remoto
Las siguientes acciones las realizaremos en el servidor de escucha "postgres1".
| apt update && apt -y upgrade && apt -y install postgresql-9.6
|
- Configuramos postgres para que accepte conexiones desde una ip(red):
| sed -ri "s/.*listen_addresses.*/listen_addresses = \'192.168.1.23, localhost\'/g" /etc/postgresql/9.6/main/postgresql.conf
|
La ip especificada es la de la propia máquina que estamos configurando.
Con esto podemos conectarnos a ese servidor en local y desde la red "192.168.1/24".
- Reiniciamos Postgres para realizar los cambios:
| systemctl restart postgresql.service
|
- Configuramos la autenticación del cliente:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | echo '''
# TYPE DATABASE USER ADDRESS METHOD
local all postgres peer
# "local" is for Unix domain socket connections only
local all all peer
# IPv4 local connections:
host all all 127.0.0.1/32 md5
host all all 192.168.1.31/24 md5
# IPv6 local connections:
host all all ::1/128 md5
''' > /etc/postgresql/9.6/main/pg_hba.conf
|
La línea señalada es la que añadimos. Con esto permitimos autenticaciones para la máquina con IP "192.168.1.31" y con el método "md5" que es el de por defecto de los usuarios de la base de datos.
peer
es la autenticación mediante usuarios del sistema con el que estemos logueados.
- Reiniciamos Postgres para realizar los cambios:
| systemctl restart postgresql.service
|
Habilitamos extensión dblink
Esto lo realizamos en el servidor desde el cual realizaremos las consultas.

- Desde Postgresql 9.1 en adelante algunas extensiones se pueden habilitar de forma simple con:
CREATE EXTENSION
- Por defecto la extensión se crea en el "schema public", si queremos crearlo en otro schema:
CREATE EXTENSION dblink SCHEMA schemaprueba
Teniendo que estar ya creado dicho "schema".
- Solo los superusuarios de postgres pueden crear extensiones.
Prueba de acceso a otra base de datos en local
- Creamos una base de datos para pruebas:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 | su - postgres
createdb proyecto
createuser -l proyecto
psql
ALTER USER proyecto WITH ENCRYPTED PASSWORD 'proyecto';
GRANT ALL PRIVILEGES ON DATABASE proyecto TO proyecto;
-- DBNAME USER HOST PORT
\c proyecto proyecto localhost
CREATE TABLE catadores
(
nif VARCHAR(9),
nombre VARCHAR(30),
apellidos VARCHAR(40),
direccion VARCHAR(60),
telefono VARCHAR(9),
CONSTRAINT PK_catadores PRIMARY KEY (nif),
CONSTRAINT CC_catadores_tel UNIQUE(telefono),
CONSTRAINT CK_catadores_nif CHECK ( nif ~ '^((\d){8})[A-Z]$|^([KLMXYZ](\d){7})[A-Z]$' )
);
INSERT INTO catadores(nif,nombre,apellidos,direccion,telefono) VALUES
('20666978Y','Arturo','Valle Segura','Rambla Mayor 34','702942135'),
('X0844055R','Gonzalo','Rubio Catalan','Pasaje Real 21','702701555'),
('07773532S','Jessica','Martos Arranz','Cuesta Iglesia, Portal 1, 2ºB','602858378'),
('Y0353214V','Laia','Palomo Robles','Cuesta Pedralbes 87','703571606'),
('79698934R','Iker','Gallardo Merino','Vereda Real, Portal 3, Escalera 8','708796631'),
('Z7932683B','Esmeralda','Benitez Alonso','Ronda Iglesia 138','601949104');
|
- Consultamos a la base de datos de "proyecto" desde el usuario y base de datos "postgres":
| SELECT * FROM dblink('dbname=proyecto','SELECT nif,nombre FROM catadores') AS P(nif VARCHAR(9),nombre VARCHAR(30));
|

- Especificamos nombre de base de datos.
- Especificamos "SELECT" a relizar.
- Es obligatorio definir el tipo de registro de las columnas a consultar (El tamaño no es obligatorio).
Prueba de acceso a otra base de datos en remoto
Teniendo configurado la primera máquina para escuche remotamente y habiendo ya creado la extension en la máquina segunda, procedemos con lo siguiente.
- Podemos crear una conexión persistente con la base de datos remota y así no tener que especificar los datos de conexión:
| SELECT dblink_connect('dblink1','dbname=proyecto host=192.168.1.23 user=proyecto password=proyecto');
|
- Realizamos consulta remota:
| SELECT * FROM dblink('dblink1','SELECT nif,nombre FROM catadores') AS P(nif VARCHAR(9),nombre VARCHAR(30));
|
- Al cerrar la sesión se finalizan las conexiones persistentes.

Para conexiones con usuarios no privilegiados relizamos lo siguiente.
| su - postgres
createuser -l remoto
psql
ALTER USER remoto WITH ENCRYPTED PASSWORD 'remoto';
-- ACTUAL DATABASE (-)
\c - remoto localhost
|
- Consultamos a la base de datos de "proyecto" del servidor de escucha desde un usuario nuevo en el servidor 2:
| SELECT dblink_connect('dblink1','dbname=proyecto host=192.168.1.23 user=proyecto password=proyecto');
SELECT * FROM dblink('dblink1','SELECT nif,nombre FROM catadores') AS P(nif VARCHAR(9),nombre VARCHAR(30));
|

En el caso de que queramos realizar consultas remotas desde las bases de datos de usuarios no privilegiados tendremos que crear la extensión "dblink" en su base de datos.
- Creación extensión en base de datos de usuario remoto:
| su - postgres
createdb remoto_db
psql
GRANT ALL PRIVILEGES ON DATABASE remoto_db TO remoto;
\c remoto_db
CREATE EXTENSION dblink;
\c remoto_db remoto localhost
|
| SELECT dblink_connect('dblink1','dbname=proyecto host=192.168.1.23 user=proyecto password=proyecto');
SELECT * FROM dblink('dblink1','SELECT nif,nombre FROM catadores') AS P(nif VARCHAR(9),nombre VARCHAR(30));
|

- Podemos ver un ejemplo de que si no tenemos creada la extensión en la base de datos de remoto no funciona:
| su - postgres
psql
\c remoto_db
DROP EXTENSION dblink;
\c remoto_db remoto localhost
SELECT dblink_connect('dblink1','dbname=proyecto host=192.168.1.23 user=proyecto password=proyecto');
|

Nos dice que no encuentra la función "dblink".
Interconexión entre BBDD Oracle y Postgres(o MariaDB) con Heterogeneus Services
Escenario vagrant
En este apartado utilizaremos un servidor con Oracle y otro con postgres.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 | Vagrant.configure("2") do |config|
config.vm.define "nodo1" do |nodo1|
config.vm.provider "virtualbox" do |vb|
vb.name = "oracle1"
vb.memory = 2048
vb.cpus = 1
end
nodo1.vm.box = "neko-neko/centos6-oracle-11g-XE"
nodo1.vm.hostname = "oracle1"
nodo1.vm.network "public_network",
bridge: "wlan0",
use_dhcp_assigned_default_route: true
end
config.vm.define "nodo2" do |nodo2|
config.vm.provider "virtualbox" do |vb|
vb.name = "postres1"
vb.cpus = 1
end
nodo2.vm.box = "debian/stretch64"
nodo2.vm.hostname = "postgres1"
nodo2.vm.network "public_network",
bridge: "wlan0",
use_dhcp_assigned_default_route: true
end
end
|
Configuración de Postgres para acceso remoto
Las siguientes acciones las realizaremos en el servidor de escucha "postgres1".
- Configuramos postgres para que accepte conexiones desde una ip(red):
| sed -ri "s/.*listen_addresses.*/listen_addresses = \'192.168.1.27, localhost\'/g" /etc/postgresql/9.6/main/postgresql.conf
|
- Configuramos la autenticación del cliente:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | echo '''
# TYPE DATABASE USER ADDRESS METHOD
local all postgres peer
# "local" is for Unix domain socket connections only
local all all peer
# IPv4 local connections:
host all all 127.0.0.1/32 md5
host all all 192.168.1.23/24 md5
# IPv6 local connections:
host all all ::1/128 md5
''' > /etc/postgresql/9.6/main/pg_hba.conf
|
- Reiniciamos Postgres para realizar los cambios:
| systemctl restart postgresql.service
|
- Creamos una base de datos para pruebas:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 | su - postgres
createdb proyecto
createuser -l proyecto
psql
ALTER USER proyecto WITH ENCRYPTED PASSWORD 'proyecto';
GRANT ALL PRIVILEGES ON DATABASE proyecto TO proyecto;
-- DBNAME USER HOST PORT
\c proyecto proyecto localhost
CREATE TABLE catadores
(
nif VARCHAR(9),
nombre VARCHAR(30),
apellidos VARCHAR(40),
direccion VARCHAR(60),
telefono VARCHAR(9),
CONSTRAINT PK_catadores PRIMARY KEY (nif),
CONSTRAINT CC_catadores_tel UNIQUE(telefono),
CONSTRAINT CK_catadores_nif CHECK ( nif ~ '^((\d){8})[A-Z]$|^([KLMXYZ](\d){7})[A-Z]$' )
);
INSERT INTO catadores(nif,nombre,apellidos,direccion,telefono) VALUES
('20666978Y','Arturo','Valle Segura','Rambla Mayor 34','702942135'),
('X0844055R','Gonzalo','Rubio Catalan','Pasaje Real 21','702701555'),
('07773532S','Jessica','Martos Arranz','Cuesta Iglesia, Portal 1, 2ºB','602858378'),
('Y0353214V','Laia','Palomo Robles','Cuesta Pedralbes 87','703571606'),
('79698934R','Iker','Gallardo Merino','Vereda Real, Portal 3, Escalera 8','708796631'),
('Z7932683B','Esmeralda','Benitez Alonso','Ronda Iglesia 138','601949104');
|
Instalación y configuración Driver ODBC
Las siguientes acciones las realizaremos en el servidor donde tenemos Oracle para conectarnos a la de Postgres.
ODBC (Open DATABASE Connector) es un estándar de acceso a las bases de datos con la que es posible acceder a los datos desde una aplicación a un gestor de base de datos cualquiera. Se puede decir que es un intermediario entre aplicación y base de datos.
| yum -y install postgresql-odbc unixODBC
|
unixODBC
son utilidades para este driver.
- En Debian los paquetes serían
odbc-postgresql
y unixodbc
.
Por defecto se nos crea la configuración del driver para conexiones con postgresql y mysql en el fichero /etc/odbcinst.ini
.

- Cambiamos la configuración:
| echo '''
[PostgreSQL]
Description = ODBC for PostgreSQL
Driver = /usr/lib64/psqlodbc.so
Setup = /usr/lib64/libodbcpsqlS.so
FileUsage = 1
''' > /etc/odbcinst.ini
|
- El problema que he encontrado es que la configuración por defecto no funciona ya que los "drivers" se encuentran en
/usr/lib64/
y no en /usr/lib/
que es como está por defecto.
- Comprobar la configuración de drivers:

- Configuramos la conexión que realizaremos con el driver:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | echo '''
[PSQL]
Debug = 0
CommLog = 0
ReadOnly = 1
Driver = PostgreSQL
Servername = 192.168.1.27
Username = proyecto
Password = proyecto
Port = 5432
Database = proyecto
Trace = 0
TraceFile = /tmp/sql.log
''' > /etc/odbc.ini
|
Los datos especificados en este fichero son los datos de conexión hacia la base de datos de postgres.
- Comprobar la configuración de la conexión del driver:

- Realizamos una comprobación de la conexión:

Vemos que ya podemos realizar consultas.
- Si por ejemplo paramos el servidor de postgres nos dará error:

Configuración de HS(Heterogeneus Services) en Oracle
- Creamos el fichero de inicio para HS:
| echo '''
HS_FDS_CONNECT_INFO = PSQL
HS_FDS_TRACE_LEVEL = ON
HS_FDS_SHAREABLE_NAME = /usr/lib64/psqlodbc.so
HS_LANGUAGE = AMERICAN_AMERICA.WE8ISO8859P1
set ODBCINI=/etc/odbc.ini
''' > $ORACLE_HOME/hs/admin/initPSQL.ora
|
HS_FDS_SHAREABLE_NAME
es el driver especificado en /etc/odbcinst.ini
.
set ODBCINI
es el fichero de configuración de los drivers ODBC.
- Importante utilizar el idioma especificado y no otro ya que propicia a errores.
Configuración del Listener en Oracle
- Definiremos una especie de entrada en el Listener que habilitará la escucha de Oracle hacia el driver ODBC:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 | echo '''
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
)
)
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = XE)
(GLOBAL_DBNAME = XE)
(ORACLE_HOME = /u01/app/oracle/product/11.2.0/xe)
)
(SID_DESC =
(SID_NAME = PSQL) # Nombre especificado en HS y en conexión del driver
(PROGRAM = dg4odbc)
(ORACLE_HOME = /u01/app/oracle/product/11.2.0/xe)
)
)
DEFAULT_SERVICE_LISTENER = (XE)
''' > $ORACLE_HOME/network/admin/listener.ora
|
- Reiniciamos el servicio del listener:
| lsnrctl stop && lsnrctl start
|
- Vemos el estado del listener:

Configuración del TNSnames en Oracle
- Creamos una entrada para "mapear" la conexión hacia el driver ODBC:
| echo '''
PSQL =
(DESCRIPTION=
(ADDRESS=(PROTOCOL=tcp)(HOST = localhost)(PORT=1521))
(CONNECT_DATA=(SID=PSQL))
(HS=OK)
)
''' >> $ORACLE_HOME/network/admin/tnsnames.ora
|
- Realizamos una prueba con tnsping:

Ahora necesitamos configurar dicho enlace en el cliente desde "sqlplus".
| CREATE DATABASE LINK LINK_POSTGRES1
CONNECT TO "proyecto"
IDENTIFIED BY "proyecto"
USING 'PSQL';
|
- Consulta a la base de datos de "postgres1" desde "oracle1":
| SELECT *
FROM "catadores"@LINK_POSTGRES1;
|

Interconexión entre BBDD Postgres --> Oracle
PROXIMAMENTE...