Slony1 - Replikace pro PostgreSQL (8)

11. 11. 2004
Doba čtení: 4 minuty

Sdílet

Při čtení tohoto seriálu jsem zjistil, že mi omylem vypadl díl věnovaný replikaci sekvencí. V dnešním dílu se na ně tedy podíváme.

V šestém dílu jsme vytvořili tabulku Božích jmen – godnames.

> psql master
master=# \d godnames
Table "public.godnames"
 Column |  Type   | Modifiers
--------+---------+-----------
 number | integer | not null
 name   | text    | not null
Indexes:
 "godnames_pkey" primary key, btree (number)
Triggers:
 _dharma_denyaccess_5 BEFORE INSERT OR DELETE OR UPDATE ON godnames FOR EACH
ROW EXECUTE PROCEDURE _dharma.denyaccess('_dharma') 

Tato tabulka měla kromě demonstrace sekvencí sloužit i jako ukázka použití Unicode znaků v tabulce. Naneštěstí však nemám fonty pro Hebrejštinu, a tak se budeme muset spokojit s latinkou.

master=# insert into godnames values (1,'Jahve');
ERROR:  Slony-I: Table godnames is replicated and cannot be modified on a subscriber node
master=# 

Tabulku můžeme modifikovat pouze na zdrojovém uzlu. To, že se jedná o c1slave2, zjistíme pomocí:

master=# set search_path = '_dharma';SELECT * from sl_set  where set_id=2;
 set_id | set_origin | set_locked | set_comment
--------+------------+------------+------------------------
      2 |          4 |            | Slave replication demo
master=# SELECT * from sl_path where pa_server=4;
pa_server | pa_client |      pa_conninfo | pa_connretry
4             2       | dbname=c1slave2  | 10
4             1       | dbname=c1slave2 .| 10

master=# \c c1slave2
You are now connected to database "c1slave2".
c1slave2=# insert into godnames values (1,'Jahve');
INSERT 11434835 1
c1slave2=# 

Pro zajímavost se můžeme pro porovnání mrknout na replikační trigery i na tomto uzlu:

c1slave2=# \d godnames
Table "public.godnames"
 Column |  Type   | Modifiers
--------+---------+-----------
 number | integer | not null
 name   | text    | not null
Indexes:
  "godnames_pkey" primary key, btree (number)
Triggers:
 _dharma_logtrigger_5 AFTER INSERT OR DELETE OR UPDATE ON godnames FOR EACH ROW EXECUTE PROCEDURE _dharma.logtrigger('_dharma', '5', 'kv') 

Vytvoříme sekvenci, která bude automaticky číslovat záznamy v tabulce. S číslováním začneme od 200, aby nekolidovalo s již existujícímy záznamy.

c1slave2=# create SEQUENCE godnames_seq minvalue 200 no cycle;
CREATE SEQUENCE
c1slave2=# alter TABLE godnames ALTER COLUMN number  SET DEFAULT nextval('publi
c.godnames_seq');
ALTER TABLE 

A přidáme další záznam, který nám sekvence automaticky očísluje:

c1slave2=# insert into godnames(name) values ('Jehova');
INSERT 11434840 1

čímž dostaneme:

c1slave2=# SELECT * from godnames;
  number |  name
 --------+--------
     100 | Allah
       1 | Jahve
     200 | Jehova
 (3 rows)

V současné době Slony1 neumí přidávat objekty do setu, který se již replikuje. Slony1 však umí sety slučovat, což se v praxi používá právě pro tento případ.

CREATE SET ( ID = 99, ORIGIN = 4, COMMENT = 'Replikace sekvence' );
SET ADD SEQUENCE ( SET ID=99, ORIGIN=4, ID=6, FULLY QUALIFIED NAME='public.godna
mes_seq'); 

Předtím, než můžeme tento set sloučit s již existujícím setem č. 2, je nutné přihlásit ostatní uzly k odběru dat.

SUBSCRIBE SET ( ID = 99, PROVIDER = 4, RECEIVER = 1, FORWARD = YES );
SUBSCRIBE SET ( ID = 99, PROVIDER = 1, RECEIVER = 2, FORWARD = NO ); 

Pokud tyto příkazy uvedeme příliš rychle po vytvoření setu, můžeme dostat chybu:

> slonik < setup.slonik
<stdin>:8: PGRES_FATAL_ERROR select "_dharma".subscribeSet(99, 4, 2, 'f');  - ERROR:  Slony-I: set 99 not found 

Tuto chybu jsem se snažil vyřešit pomocí příkazu DROP SET, jehož provedení na uzlu č. 2 v nešťastnou chvíli (Slony neměl ještě zpracovanou subscribe zprávu) způsobilo, že to Slony1 již nerozchodil a musel jsem mu poeditovat systémový katalog, kde jsem označil tuto zprávu za zpracovanou, abych uzel č. 2 znovu sesynchronizoval se zbytkem clusteru. Zde vidíte praktické uplatnění znalostí mechanismu předávání zpráv, který byl probírán na začátku seriálu.

Tato zkušenost opět ukázala, že se u Slony vyplatí počkat, pokud jsou konfigurační příkazy slonika vzájemně závislé. Slonik je sice vybavem příkazem WAIT FOR EVENT, který byl navržen na řešení těchto situací, ale tento příkaz má zase své problémy.

Slony1 neumí při replikaci vytvářet replikované tabulky, to samé platí i pro sekvence. Sekvence je nutné ručně vytvořit na všech uzlech. CREATE SEQUENCE public.godnames_seq; postačí.

Jak jsme si již ukázali v úvodu tohoto dílu, tabulky jsou na ostatních uzlech zamčené a nelze je modifikovat. Pro sekvence toto omezení neplatí:

master=# SELECT nextval('godnames_seq');
 nextval
---------
     201
(1 row)
master=# SELECT nextval('godnames_seq');
 nextval
---------
     202
 (1 row)

Na toto omezení si v praxi budete muset dávat pozor. Nyní můžeme již konečně sloučit sety 99 a 2.

MERGE SET ( ID=2, ADD ID=99, ORIGIN = 4);

Na což master uzel patřičně zareaguje a dojde ke sloučení dvou setů.

bitcoin školení listopad 24

DEBUG2 remoteWorkerThread_4: syncing set 99 with 0 table(s) from provider 4
DEBUG2 remoteWorkerThread_4: syncing set 2 with 1 table(s) from provider 4
DEBUG2 remoteHelperThread_4_4: 0.060 seconds delay for first row
DEBUG2 remoteHelperThread_4_4: 0.064 seconds until close cursor
DEBUG2 remoteWorkerThread_4: new sl_rowid_seq value: 4000000000003972
DEBUG2 remoteWorkerThread_4: SYNC 700 done in 0.564 seconds
DEBUG2 remoteWorkerThread_4: Received event 4,701 MERGE_SET
CONFIG dropSet: set_id=99
DEBUG2 sched_wakeup_node(): no_id=4 (0 threads + worker signaled)
DEBUG2 remoteWorkerThread_4: Received event 4,702 SYNC
DEBUG2 remoteWorkerThread_4: SYNC 702 processing
DEBUG2 remoteWorkerThread_4: syncing set 2 with 1 table(s) from provider 4
DEBUG2 remoteHelperThread_4_4: 0.009 seconds delay for first row
DEBUG2 remoteHelperThread_4_4: 0.012 seconds until close cursor
DEBUG2 remoteWorkerThread_4: new sl_rowid_seq value: 4000000000003972
DEBUG2 remoteWorkerThread_4: SYNC 702 done in 0.071 seconds 

Při synchonizaci se opraví i námi pootočená sekvence zpět na hodnotu nastavenou na zdrojovém uzlu.

master=# SELECT last_value from godnames_seq;
last_value
------------
      200
(1 row)

To by bylo vše k sekvencím a ke slučování setů. Sekvence se navíc nereplikují příliš často, já jsem je v praxi zatím replikovat nepotřeboval.