Re: Replicacion

From: cbeltran <cbeltran(at)roldan(dot)net>
To: Oswaldo Hernández <listas(at)soft-com(dot)es>
Cc: AyudaPostgres <pgsql-es-ayuda(at)postgresql(dot)org>
Subject: Re: Replicacion
Date: 2005-02-24 14:25:37
Message-ID: 000801c51a7c$b6f67840$272615ac@tania
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-es-ayuda


Oswaldo,

Los aspectos que mencionas sobre "seguridad al tener este centro escuchando
directamente por internet", definicion agrupada de gran cantidad de
movimientos provenientes de un servidor en una misma "transaccion en el
servidor central", mas otros que mencionas fueron objeto de controversia en
nuestro primer diseño y por supuesto estamos pendientes de evolucionar
nuestro esquema de replica/sincronizacion para un siguiente release. Me
parece importante cruzar estos conceptos para efectos de mejora y por lo
tanto voy a plantear el esquema con mayor detalle.

La base de datos tiene diseño identico en los servidores maestros y en el
servidor central y las tablas se clasificaron asi:

- Tablas maestras puras. (No son replicadas ni sincronizadas)
- Tablas maestras operativas. (SI son replicadas y SI son sincronizadas)
- Tablas de movimiento. (SI son replicadas y NO son sincronizadas)
- Tablas de edicion. (Practicamente temporales y No son replicadas ni
sincronizadas)

Para poder identificar en que servidor (Oficina) se ingreso una linea de
cualquier tabla se estableció lo siguiente (Una tabla por ejemplo terceros)
luce asi:

CREATE SEQUENCE terceros_id_seq start XX0000001 increment 1 maxvalue
999999999 minvalue 000000001 cache 1 ;
CREATE TABLE terceros (
terceros_id integer DEFAULT nextval('terceros_id_seq'::text) NOT NULL,
tercero integer NOT NULL,
digito_verificacion char(1),
etc...
Y terceros_id es PRIMARY KEY con XX prefijo del serial y así evitando el
choque en el servidor central, además de identificar el server que hizo el
insert original de la linea.

Las tablas maestras operativas y de movimiento (replicables) residen en una
tabla llamada tablas_replica con la siguiente estructura:

CREATE SEQUENCE tablas_replica_id_seq start 180000001 increment 1 maxvalue
999999999 minvalue 000000001 cache 1 ;
CREATE TABLE tablas_replica (
tablas_replica_id integer DEFAULT nextval('tablas_replica_id_seq'::text)
NOT NULL,
tabla_nombre_replica character(90) NOT NULL,
CONSTRAINT pk_tablas_replica PRIMARY KEY (tablas_replica_id)
);

de tal manera que un trigger para la tabla terceros inserta una linea en la
tabla control_replica de la siguiente estructura:

CREATE SEQUENCE control_replica_id_seq start 180000000000000001 increment 1
maxvalue 999999999999999999 minvalue 000000000000000001 cache 1 ;
CREATE TABLE control_replica (
control_replica_id bigint DEFAULT
nextval('control_replica_id_seq'::text) NOT NULL,
tablas_replica_id integer NOT NULL,
linea_tabla_replica_id bigint NOT NULL,
operacion character(6),
CONSTRAINT pk_control_replica PRIMARY KEY (control_replica_id),
CONSTRAINT fk_tablas_replica_id1 FOREIGN KEY (tablas_replica_id)
REFERENCES tablas_replica(tablas_replica_id) ON UPDATE CASCADE ON DELETE
CASCADE
);

Dicho trigger es:

CREATE FUNCTION "rp_terceros"() RETURNS TRIGGER AS '
BEGIN
IF TG_OP = ''DELETE'' THEN
INSERT INTO control_replica (tablas_replica_id,
linea_tabla_replica_id, operacion) VALUES (180000002,OLD.terceros_id,
TG_OP);
RETURN OLD;
END IF;
IF TG_OP = ''INSERT'' THEN
INSERT INTO control_replica (tablas_replica_id,
linea_tabla_replica_id, operacion) VALUES (180000002,NEW.terceros_id,
TG_OP);
RETURN NEW;
END IF;
IF TG_OP = ''UPDATE'' AND OLD.terceros_id = NEW.terceros_id THEN
INSERT INTO control_replica (tablas_replica_id,
linea_tabla_replica_id, operacion) VALUES (180000002,NEW.terceros_id,
TG_OP);
RETURN NEW;
END IF;
END;
' LANGUAGE 'plpgsql';
CREATE TRIGGER rp_terceros BEFORE INSERT OR UPDATE OR DELETE ON terceros FOR
EACH ROW EXECUTE PROCEDURE rp_terceros();

Es decir tablas_replica_id, para el caso de la tabla "terceros" es 180000002
y linea_tabla_replica_id almacena terceros_id que es el PRIMARY KEY de la
línea objeto de la operacion.

Con este diseño no se necesita almacenar en el control los contenidos de esa
linea sino unicamente el id correspondiente. Por supuesto se presentan casos
tales como sucesivos updates en el control acumulados que al replicar con el
primero hubiera bastado. Otro caso puede ser que un update precedido de un
delete, al replicar, ya no encuentre la línea y se considera un update dummy
para que posteriormente si se efectue en el servidor central el delete y
bueno, podrían haber otros casos

Con este control generandose en los servers maestros el servidor central con
hilo de ejecucion por server esta continuamente replicando al central y
sincronizando. La estrategia de replicado es obtener la operacion (D/U/I) y
con el nombre de cada tabla y el id de la línea de esa tabla
(linea_tabla_replica_id) en orden de generacion del control_replica se
obtiene el contenido de dicha linea del server maestro y se hace la
respectiva operacion en el central para luego borrar del server central la
línea de control. Las operaciones imposibles de llevar a cabo en el server
central se escriben en un archivo de log tambien por hilo de ejecucion
borrando también el control. Esta estrategia permite asegurar que en caso de
interrupcion de conexiones la linea de control de un momento dado sin borrar
repite la operacíon en servidor central sin ningun riesgo de perdida de
informacion.

El esquema de sincronizacion es similar pero con un control adicional de
linea a sincronizar por server.

Carlos Beltran V.
Roldan SIA SA Bogota, Colombia.

In response to

Responses

Browse pgsql-es-ayuda by date

  From Date Subject
Next Message Mario Gonzalez 2005-02-24 14:34:47 Re: Query Falso
Previous Message Edwin Quijada 2005-02-24 14:18:38 RE: clientes graficos