web-dev-qa-db-fra.com

Comment la mise à jour de la gâchette dans la base de données des répliques sur Postgres?

Dans les deux serveurs (maître et réplique), j'ai deux tables comme ceci:

CREATE TABLE my_table
(
    id SERIAL,
    name TEXT,
    "timestamp" timestamp without time zone,
    CONSTRAINT my_table_pkey PRIMARY KEY (id)
);

Dans mon serveur maître, j'ai créé une publication avec:

CREATE PUBLICATION sync_publication;
ALTER PUBLICATION sync_publication ADD TABLE my_table;

Ensuite, j'ai créé une utilisation (nommée syncguy):

CREATE ROLE syncguy WITH REPLICATION LOGIN PASSWORD 'root';

Après avoir acquis des privilèges:

GRANT ALL PRIVILEGES ON DATABASE my_database TO syncguy;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO syncguy;

Dans postgresql.conf Configuration wal_level à logique:

wal_level = logical

Dans postgresql.conf Configuration Wal_level à la réplique:

wal_level = replica

Ensuite, j'insère en maître:

insert into public.my_table (id, name, "timestamp") values (
    uuid_generate_v4(),
    'foo',
    current_timestamp
);

Puis dans les deux serveurs en my_table Je reçois:

+--------------------------------------+------+----------------------------+
| id                                   | name | timestamp                  |
+--------------------------------------+------+----------------------------+
| 157b1849-53a5-4206-9f8b-961c1485d20d | foo  | 2020-02-04 10:07:28.048819 |
+--------------------------------------+------+----------------------------+

Ensuite, je mettez à jour "Nom Col" en Master à bar valeur, et j'entre dans les deux serveurs.

+--------------------------------------+------+----------------------------+
| id                                   | name | timestamp                  |
+--------------------------------------+------+----------------------------+
| 157b1849-53a5-4206-9f8b-961c1485d20d | bar  | 2020-02-04 10:07:28.048819 |
+--------------------------------------+------+----------------------------+

Tout cela a bien fonctionné, mon problème est lorsque je crée un déclencheur, j'utilise cette fonction et déclencheur sur réplique serveur (je n'utilise pas de déclencheurs dans "Master Server"):

CREATE FUNCTION public.my_func() RETURNS trigger
    LANGUAGE plpgsql
    AS $$DECLARE
    partition_date TEXT;
    partition TEXT;
BEGIN
    partition_date := to_char(NEW.timestamp, 'YYYY_MM_DD');
    partition := 'messages_' || partition_date;

    EXECUTE 'CREATE TABLE IF NOT EXISTS ' || partition || ' (CONSTRAINT ' || partition || '_pkey UNIQUE (id)) INHERITS (' || TG_RELNAME || ');';
    EXECUTE 'INSERT INTO ' || partition || ' SELECT(' || TG_RELNAME || ' ' || quote_literal(NEW) || ').* RETURNING id;';

    RETURN NULL;
END;$$;

ALTER FUNCTION public.my_func() OWNER TO postgres;

CREATE TRIGGER my_trigger BEFORE INSERT ON public.my_table FOR EACH ROW EXECUTE FUNCTION public.my_func();

ALTER TABLE public.my_table ENABLE REPLICA  TRIGGER my_trigger;

Donc, mon objectif avec ce déclencheur est de partitionner mes données répliquées, lorsque j'insère en maître avec la gâchette dans le serveur de répliqué. Créer une table comme si ceci messages_2020_02_04

Le messages_2020_02_04 contient mes données répliquées et My_Table dans Replica Server n'est que "référencée", comme je l'ai dit, cela fonctionne bien avec insert (j'ai testé l'envoi de plusieurs personnes, toutes sont allées aux tableaux générés par la gâchette), mais lors de l'exécution de "mise à jour" dans Master Les lignes ne sont pas mises à jour dans la réplique.

Est-il possible de travailler sur des mises à jour principales avec une réplique et des déclencheurs dans "Replica Server"?

3

Le problème avec les mises à jour de votre scénario est que my_table Sur le serveur de secours ne contient pas la ligne mise à jour, de sorte que le UPDATE ne fait rien et aucun déclencheur de niveau de ligne n'est tiré. Puisque rien n'a été inséré dans my_table, un UPDATE ne peut pas être reproduit.

Si vous souhaitez reproduire d'une table non partitionnée à une table partitionnée avec une réplication logique, utilisez PostgreSQL V13 ou mieux, où cela est pris en charge. Vous serez capable de générer automatiquement des partitions de cette façon, mais cela ne devrait pas être un problème de créer les partitions avant de commencer à reproduire.

1
Laurenz Albe