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"?
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.