Replicando datos con PostgreSQL 馃悩

Publicado el 14.05.2023 a las 21:51

Replicando datos con PostgreSQL 馃悩

  1. Replicar datos en bases de datos de PostgreSQL en servidores separados?

    • 驴Por qu茅 uso FDW y no replico la base de datos completa?

    • Arquitectura que usaremos

    • Cargar la extensi贸n postgres_fdw

    • Crear servidor remoto de respaldo en servidor local

    • Creando usuario para la conexi贸n con servidor remoto de respaldo

    • Crear tabla destino en servidor remoto

    • Crear tabla para servidor remoto

    • Crear la funci贸n encargada de escribir los nuevos datos en la tabla para servidor remoto

    • Crear el trigger que llamar谩 a la funci贸n de replicar los datos

    • Pruebas

  2. Errores y soluciones

    • Error de permiso para escribir en la tabla for谩nea

    • Error de mapeo de usuario

  3. C贸mo replicar datos en una misma base de datos de PostgreSQL?

    • Crear las tablas de origen y de replicaci贸n

    • Crear la funci贸n encargada de escribir los nuevos datos en la tabla de replicaci贸n

    • Crear el trigger que llamar谩 a la funci贸n de replicar los datos

    • Pruebas dentro de la misma base de datos

  4. 驴C贸mo s茅 qu茅 versi贸n de PostgreSQL estoy usando?

  5. 驴C贸mo iniciar sesi贸n en PgAdmin con otro usuario?

Logo de fjmduran

Replicando datos con PostgreSQL 馃悩

Esta semana he estado viendo c贸mo poder sincronizar datos en PostgreSQL sin necesidad de software de terceros.


Hasta ahora no hab铆a tenido la necesidad de hacerlo con PostgreSQL, ya que hasta la fecha estaba usando Microsoft SQL Server y tiene su propio software de replicaci贸n.


PostgreSQL no tiene uno parecido al de MS SQL Server, as铆 que lo he implementado de la siguiente manera.


Lo que hago es que cada vez que se inserte una nueva fila en una tabla que quiero sincronizar, se dispara una funci贸n que coger谩 esa misma fila y la guardar谩 en una tabla de respaldo ubicada en otro servidor.


    Los pasos que seguir茅 ser谩n:
  1. Crear la tabla de datos de origen
  2. Crear el servidor remoto en el servidor origen
  3. Crear una conexi贸n al servidor remoto desde el servidor origen
  4. Crear una tabla en la base de datos local que se enlazar谩 a otra en el servidor de respaldo o de destino
  5. Crear la tabla de datos destino en el servidor remoto
  6. Crear la funci贸n encargada de recibir la nueva fila y hacer la escritura en la tabla de datos replicados
  7. Crear el disparador que se encargar谩 de llamar a la funci贸n anterior cuando se a帽adan nuevos datos en la tabla de datos de origen.
  8. Ejecutar pruebas

Replicar datos en bases de datos de PostgreSQL en servidores separados

Para replicar una tabla usar茅 el mecanismo de Foreign Data Wrapper (FDW) que nos permite acceder a datos de una tabla almacenados en un servidor externo como si estuvieran en una tabla en la base de datos local.

驴Por qu茅 uso FDW y no replico la base de datos completa?

Podr铆a replicar toda la base de datos.


La replicaci贸n nos permite crear copias exactas de una base de datos en uno o varios servidores secundarios, que se mantienen actualizadas en tiempo real a medida que se realizan cambios en la base de datos principal.


Para replicar una base de datos en PostgreSQL, se utiliza la herramienta pg_basebackup para crear una copia inicial de la base de datos principal en el servidor secundario, y luego se utiliza la configuraci贸n de replicaci贸n para mantener actualizada la copia en el servidor secundario a medida que se realizan cambios en la base de datos principal.


Una vez que se ha replicado la base de datos en el servidor secundario, se puede acceder a las tablas remotas como si fueran tablas locales en el servidor secundario.


Esto puede ser m谩s r谩pido y eficiente que utilizar FDW, ya que no requiere la transferencia de datos a trav茅s de la red para cada consulta.


No obstante, la replicaci贸n tambi茅n tiene sus desventajas, ya que puede consumir una cantidad significativa de recursos en el servidor principal y secundario, y requiere una configuraci贸n y monitoreo cuidadosos para garantizar la integridad y consistencia de los datos replicados.


Como en este ejemplo s贸lo quiero mantener replicados datos de una sola tabla utilizar茅 el mecanismo de Foreign Data Wrapper (FDW).


Un FDW permite acceder a datos almacenados en un servidor externo como si estuvieran en una tabla local en la base de datos actual.


Para hacer referencia a una tabla remota a trav茅s de un FDW, tendr谩s qu茅:


  1. Cargar la extensi贸n postgres_fdw
  2. Crear el servidor remoto
  3. Crear una conexi贸n al servidor remoto
  4. Crear una tabla remota en la base de datos local

Una vez creada la tabla remota, podr谩s acceder a ella como si fuera una tabla local utilizando consultas SQL regulares.


馃毄 Antes de comenzar, aseg煤rate que las versiones de PostgreSQL en cada servidor sean compatibles para hacer la conexi贸n.

Arquitectura que usaremos

En el servidor local replicaremos una tabla que se llamara tabla_origen y cada vez que se inserte un nuevo dato se disparar谩 un trigger que se llamar谩 trigger_replica_en_remoto.

El trigger ejecutar谩 una funci贸n llamada funcion_replica_para_servidor_remoto que se encargar谩 en encribir en una tabla local llamada tabla_destino_para_servidor_remoto enlazada con el servidor remoto mediante un foreign server llamado server_13_2.


En el servidor remoto s贸lo tendremos una tabla llamada tabla_destino_en_servidor_remoto con la misma estructura que la tabla tabla_origen.

Diagrama de arquitectura para replicar tabla en PostgreSQLVista de elementos para replicar tabla en PostgreSQL con PGAdmin

Cargar la extensi贸n postgres_fdw

Para habilitar el conector de datos externos, en ambos servidores principal y de respaldo, ejecutar:

CREATE EXTENSION IF NOT EXISTS postgres_fdw;
Vista de PGAdmin de la extensi贸n fdw cargada satisfactoriamente

Crear servidor remoto de respaldo en servidor local

Crearemos una especie de servidor PostgreSQL virtual en nuestro servidor local

CREATE SERVER server_13_2 
FOREIGN DATA WRAPPER postgres_fdw 
OPTIONS (host 'ip_servidor', port 'puerto', dbname 'nombre_base_de_datos');
Vista de PGAdmin de la conexi贸n a servidor externo satisfactoria

Creando usuario para la conexi贸n con servidor remoto de respaldo

CREATE USER MAPPING FOR usuario_con_el_que_te_quieres_conectar
SERVER server_13_2
OPTIONS (user 'user', password 'password');
Vista de PGAdmin de usuario de acceso a servidor virtual

Crear tabla destino en servidor remoto

En el servidor remoto o de respaldo creo la tabla que recibir谩 los datos del servidor principal o de origen.

//TABLA DESTINO EN SERVIDOR REMOTO
CREATE TABLE public.tabla_destino_en_servidor_remoto
(
  id integer,
  description character varying
)

馃毄 ten en cuenta que el usuario de PostgreSQL que vaya a escribir desde el servidor origen tenga permisos para escribir aqu铆, en la tabla destino del servidor remoto.

Crear tabla para servidor remoto

Creo la tabla en el servidor principal o de origen que enlazar谩 los datos con el servidor de respaldo o de destino.

CREATE FOREIGN TABLE tabla_destino_para_servidor_remoto (id integer, description character varying) 
SERVER server_13_2 
OPTIONS (schema_name 'public', table_name 'tabla_destino_en_servidor_remoto');
Vista de PGAdmin de tabla for谩nea

Crear la funci贸n encargada de escribir los nuevos datos en la tabla para servidor remoto

Creamos una funci贸n a la que llamaremos funcion_replica_para_servidor_remoto.


Entre las palabras reservadas BEGIN y END se escribir谩 el c贸digo de lo que se se quiera ejecutar, en nuestro caso haremos un INSERT a la tabla tabla_destino_para_servidor_remoto (creada en el punto anterior) de los nuevos valores que vienen en la variable NEW

CREATE FUNCTION  funcion_replica_para_servidor_remoto()
 RETURNS trigger
AS
$$
BEGIN
INSERT INTO tabla_destino_para_servidor_remoto VALUES (NEW.*);  
RETURN NEW;
END
$$
LANGUAGE plpgsql;
Vista de PGAdmin de funci贸n para replicaci贸n de tabla

Crear el trigger que llamar谩 a la funci贸n de replicar los datos

Crearemos un trigger o disparador que se llamar谩 trigger_replica_en_remoto que se disparar谩 cada vez que se inserte un dato en la tabla tabla_origen y ser谩 el encargado de ejecutar la funci贸n programada en el punto anterior funcion_replica_para_servidor_remoto

CREATE TRIGGER trigger_replica_en_remoto 
AFTER INSERT 
ON tabla_origen 
FOR EACH ROW 
EXECUTE FUNCTION funcion_replica_para_servidor_remoto();
      
Vista de PGAdmin de la creaci贸n de trigger para replica de tabla

Pruebas

Para probar que todo est谩 correcto a帽ade datos a la tabla_origen, yo a帽adir茅 una fila con el id = 3 y el description = test para remoto 3

INSERT INTO tabla_origen (id, description)
VALUES (3, 'test para remoto 3');
Vista de PGAdmin a帽adiendo filas a la tabla origen en una replicaci贸n

Ahora compruebo que los datos se hayan replicado en el servidor remoto o de respaldo.

Vista de PGAdmin de la comprobaci贸n de la replicaci贸n de datos

BOOM! 馃挘, disfr煤talo.

Errores y soluciones

Error de permiso para escribir en la tabla for谩nea

Un escenario en el que tuve problemas fue con una aplicaci贸n de Java que escrib铆a en PostgreSQL, pero a la hora de activar la sincronizaci贸n como te la he explicado no hac铆a los INSERT, el error que me arrojaba era:


[ERROR] com.inerco.tse.bd.BdAcceso -> insertaRegistros() -> Error al insertar

### Error updating database. Cause: org.postgresql.util.PSQLException: ERROR: permiso denegado a la tabla for谩nea tb_gas_server80 Where: sentencia SQL: 芦INSERT INTO tb_gas_server80 VALUES (NEW.*)禄 funci贸n PL/pgSQL replica_tb_gas_para_server80() en la l铆nea 3 en sentencia SQL


El tema era que cuando yo hac铆a el INSERT desde el PgAdmin, s铆 lo hac铆a bien, y era porque yo hac铆a en INSERT logueado con el usuario postgres en PgAmin.


Cuando me logue茅 en PgAdmin con el usuario que intentaba acceder el programa de Java ya consegu铆 que me saliera el error desde PgAdmin.


Si quieres saber c贸mo loguearte en PgAmin con un usuario distinto ve aqu铆


Para solventar este problema lo que hice fue asignar al usuario con el que acced铆a el programa de Java como propietario de las tablas implicadas en la r茅plica, tanto en el servidor origen como en el remoto.

ALTER TABLE nombre_tabla OWNER TO nuevo_propietario;

Error de mapeo de usuario

Te puedes encontrar con el siguiente error:


ERROR: no se encontr贸 un mapeo para el usuario 芦usuario_en_cuestion禄 CONTEXT: sentencia SQL: 芦INSERT INTO tb_gas_server80 VALUES (NEW.*)禄 funci贸n PL/pgSQL replica_gas() en la l铆nea 3 en sentencia SQL SQL state: 42704


Para solventarlo, a帽ade al usuario para que tenga acceso al servidor.


CREATE USER MAPPING FOR usuario_en_cuestion
SERVER server_13_2
OPTIONS (user 'user', password 'password');

驴Sincronizar datos en una misma base de datos de PostgreSQL?

Visto lo anterior, hacerlo en local ser谩 mucho m谩s f谩cil.

Crear las tablas de origen y de replicaci贸n

Creamos las tablas, las llamaremos tabla_origen y tabla_replicada. Cada una de las tablas con un campo id num茅rico y un campo description de texto.

//TABLA ORIGEN
CREATE TABLE public.tabla_origen
(
  id integer,
  description character varying
)

//TABLA PARA DATOS REPLICADOS
CREATE TABLE public.tabla_replicada
(
  id integer,
  description character varying
)
Vista de PGAdmin de la creaci贸n de la tabla que recibir谩 los datos replicados

Crear la funci贸n encargada de escribir los nuevos datos en la tabla de replicaci贸n

Creamos una funci贸n a la que llamaremos funcion_replica_origen.


Entre las palabras reservadas BEGIN y END se escribir谩 el c贸digo de lo que se quiera ejecutar. En nuestro caso haremos un INSERT a la tabla tabla_replicada de los nuevos valores que vienen en la variable NEW

CREATE FUNCTION  funcion_replica_origen()
 RETURNS trigger
AS
$$
BEGIN
INSERT INTO tabla_replicada VALUES (NEW.*);  
RETURN NEW;
END
$$
LANGUAGE plpgsql;
Vista de PGAdmin de la funci贸n encargada de replicar datos

Crear el trigger que llamar谩 a la funci贸n de replicar los datos

Crearemos un trigger o disparador que se llamar谩 trigger_replica_origen que se disparar谩 cada vez que se inserte un dato en la tabla tabla_origen y ser谩 el encargado de ejecutar la funci贸n programada en el punto anterior funcion_replica_origen

CREATE TRIGGER trigger_replica_origen 
AFTER INSERT 
ON tabla_origen 
FOR EACH ROW 
EXECUTE FUNCTION funcion_replica_origen();
Vista de PGAdmin de la creaci贸n del trigger que se disparar谩 despu茅s de la creaci贸n de nuevas filas en la tabla origen de la replicaci贸n

Pruebas dentro de la misma base de datos

Para probar que todo est谩 correcto a帽ade datos a la tabla_origen

INSERT INTO tabla_origen (id, description)
VALUES (1, 'test1');
Vista de PGAdmin de la creaci贸n de nueva fila en la tabla origen de replicaci贸n

Revisa que se han a帽adido los datos tanto a tabla_origen como a tabla_replicada

SELECT * FROM public.tabla_origen  
SELECT * FROM public.tabla_replicada
Vista de PGAdmin de la compraci贸n de replicaci贸n de datos

驴C贸mo s茅 qu茅 versi贸n de PostgreSQL estoy usando?

Para saber qu茅 versi贸n de PostgreSQL tienes ejecuta la instrucci贸n SQL en tu servidor:

SELECT version();

驴C贸mo iniciar sesi贸n en PgAdmin con otro usuario?

Para loguearte en PgAdmin con un usuario distinto:

  1. Descon茅ctate del servidor
  2. Con el servidor desconectado haz clic con el bot贸n derecho y pulsa en propiedades
  3. En la pesta帽a de Connection cambia el Username con el que quiere entrar
Vista de PGAdmin de la conexi贸n a una base de datos de PostgreSQL con un usuario distinto

Hasta luego 馃枛