Po předchozím dílu máme vytvořenou tuto strukturu databázových uzlů
master | | slave1 slave2 | c1slave2
Replikujeme jeden set tabulek z uzlu master na ostatní uzly. V druhém dílu seriálu jsme si řekli, že každý uzel může být zdrojem dat určených k replikaci, nezávisle na svém clusterovém statusu master/slave. V následující ukázce zreplikujeme data z uzlu c1slave2 na uzel slave1.
Budeme replikovat následující tabulku. Tabulka má primární klíč, a tak půjde bez problému replikovat.
%cat godnames.schema CREATE TABLE public.godnames ( "number" integer primary key, "name" text not null );
Vytvoření tabulky na uzlech c1slave2 a slave1
%psql c1slave2 -f godnames.schema
psql:godnames.schema:5: NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "godnames_pkey" for table "godnames"
CREATE TABLE
%psql slave1 -f godnames.schema
psql:godnames.schema:5: NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "godnames_pkey" for table "godnames"
CREATE TABLE
%
Následujícími příkazy pro slonika vytvoříme set číslo 2. Povšimněte si prosím ID nově přidané tabulky, které není 1, ale 5, protože replikační systém Slony1 nečísluje tabulky per set, ale (trochu nelogicky) globálně.
CREATE SET ( ID = 2, ORIGIN = 4, COMMENT = 'Slave replication demo' );
SET ADD TABLE ( SET ID = 2, ORIGIN = 4,
ID = 5, FULL QUALIFIED NAME = 'public.godnames',
COMMENT = 'God Names' );
Přihlásíme slave1 k odběru dat z c1slave2. Před přihlášením je nutné chvilku počkat než dorazí zprava oznamující vytvoření setu číslo 2 z uzlu c1slave2 na uzel slave1, jinak se přihlášení neprovede. Konfigurační jazyk slonik má pro tento ucel příkaz:
WAIT FOR EVENT (ORIGIN = 4, CONFIRMED = 2);
s příkazem wait for event je spojen jeden problém. Pokud provedete restart agenta slon právě v okamžiku, kdy slonik čeká na potvrzeni události, tak zůstane v systémové tabulce sl_path záznam, který následně způsobuje chybové hlášky typu:
ERROR slon_connectdb: PQconnectdb("<event pending>") failed - missing "=" after
"<event" in connection info string
ERROR remoteWorkerThread_4: cannot connect to data provider 4 on '<event pendin g>'
Tento záznam je nutné ručně odstranit, což je vsak možné pouze tehdy, když daný uzel (v našem případě s číslem 2) není subscribnut k odběru setu z uzlu c. 4. Pokud je, je nutné jej nejprve odhlásit, což však bude mít za následek opětovné vytvoření kopie setu. V praxi se tedy více než vyplatí pracovat s příkazem wait for event opatrně. Nebo jej nepoužívat a radši těch pár sekund mezi příkazy počkat. Situaci navíc komplikuje i fakt, že slonik zastaví na prvním chybně vykonaném příkazu (např. vytvoření již existujícího setu), takže si ještě navíc docela užijete i editování souboru s příkazy pro slonika.
SUBSCRIBE SET ( ID = 2, PROVIDER = 4, RECEIVER = 2, FORWARD = NO );
Provedení tohoto příkazu na uzlu č. 2 má za následek:
-
Vyslání žádosti o replikaci dat na uzel č. 4
DEBUG2 localListenThread: Received event 2,714 SUBSCRIBE_SET CONFIG storeSubscribe: sub_set=2 sub_provider=4 sub_forward='f'
-
Probuzení remoteWorker Threadu spolupracujícím s uzlem č. 4 (žádný takový tu není, uzel č. 2 je napojen pouze na uzel č. 1)
DEBUG2 sched_wakeup_node(): no_id=4 (0 threads + worker signaled)
-
Potvrzení od uzlu č. 4 o úspěšném přijetí naší žádosti k odběru dat
DEBUG2 remoteWorkerThread_4: Received event 4,200 ENABLE_SUBSCRIPTION
-
Přijetí periodické sync události z uzlu č. 4
DEBUG2 remoteWorkerThread_4: Received event 4,201 SYNC
-
Žádná replikace se s uzlem č. 4 nekoná
DEBUG2 remoteWorkerThread_4: SYNC 201 processing DEBUG2 remoteWorkerThread_4: no sets need syncing for this event
Pro lepší ilustraci vložíme jeden záznam do tabulky:
> psql c1slave2 c1slave2=# insert into godnames values(100,'Alláh'); INSERT 11289006 1 c1slave2=#
ale ani toto replikaci nenastartuje. Uzly 4 a 2 ani nadále nereplikují data. Ačkoliv jsou zprávy mezi těmito uzly bez problémů předávány, replikační systém Slony1 neumožňuje forward-only předávání replikačního žurnálu.
Námi vzniklou situaci můžeme zprovoznit dvěma způsoby:
- Vytvořením přímého spojení uzlu 4 a 2 pomocí příkazu STORE PATH.
- Přihlášením uzlu 1 a 3 do setu číslo 2 s využitím cascading slave feature.
Metoda #1
V případě číslo 1 stačí vytvořit pouze jedno spojeni, a to ve směru slave1 (2) → c1slave2 (4). Staré připojení je nutné vymazat pomocí direktivy DROP LISTEN.
STORE PATH ( client = 2,server = 4, conninfo = 'dbname=c1slave2 host=localhost user=slony password=iehovah');
DROP LISTEN ( client = 2, server = 4, provider = 1);
STORE LISTEN ( origin = 4, RECEIVER = 2);
Uzly se navzájem spojí, ale ani tato akce neaktivuje replikaci. Podíváme se tedy do katalogu na uzlu slave1, co replikaci brání. Po bližším průzkumu katalogu objevíme, že v tabulce sl_setsync se nevytvořil záznam pro set č. 2.
%psql slave1
slave1=# SELECT * from _dharma.sl_setsync ;
ssy_setid | ssy_origin | ssy_seqno | ssy_minxid | ssy_maxxid
-----------+------------+-----------+------------+-----------
1 | 1 | 2706 | 2680280 | 2680281
(1 row)
Tento problém odstraníme odhlášením a opětovným přihlášením setu.
UNSUBSCRIBE SET (ID = 2, RECEIVER = 2);
WAIT FOR EVENT (ORIGIN = 4, CONFIRMED = 2);
SUBSCRIBE SET ( ID = 2, PROVIDER = 4, RECEIVER = 2, FORWARD = NO );
Poté se již replikace konečně rozběhne:
DEBUG2 remoteWorkerThread_4: Received event 4,345 ENABLE_SUBSCRIPTION
DEBUG1 copy_set 2
DEBUG1 remoteWorkerThread_4: connected to provider DB
DEBUG2 remoteWorkerThread_4: copy table public.godnames
DEBUG2 remoteWorkerThread_4: 10 bytes copied for table public.godnames
DEBUG2 remoteWorkerThread_4: 0.129 seconds to copy table public.godnames
DEBUG2 remoteWorkerThread_4: copy_set SYNC found, use event seqno 344.
DEBUG2 remoteWorkerThread_4: 0.042 seconds to build initial setsync status
DEBUG1 remoteWorkerThread_4: disconnected from provider DB
DEBUG1 copy_set 2 done in 1.058 seconds
CONFIG enableSubscription: sub_set=2
DEBUG2 sched_wakeup_node(): no_id=4 (0 threads + worker signaled)
DEBUG1 remoteWorkerThread_4: helper thread for provider 4 created
Metoda #2
Vytvoříme tabulku i v databázích slave2 a master
% psql slave2 -f godnames.schema
psql:godnames.schema:5: NOTICE: CREATE TABLE / PRIMARY KEY will create implicit
index "godnames_pkey" for table "godnames"
CREATE TABLE
% psql master -f godnames.schema
psql:godnames.schema:5: NOTICE: CREATE TABLE / PRIMARY KEY will create implicit
index "godnames_pkey" for table "godnames"
CREATE TABLE
%
a pak tyto databáze přihlásíme k odběru dat:
UNSUBSCRIBE SET (ID = 2, RECEIVER = 2);
SUBSCRIBE SET ( ID = 2, PROVIDER = 4, RECEIVER = 3, FORWARD = YES );
SUBSCRIBE SET ( ID = 2, PROVIDER = 3, RECEIVER = 1, FORWARD = YES );
SUBSCRIBE SET ( ID = 2, PROVIDER = 1, RECEIVER = 2, FORWARD = NO );
Tímto jsme vyčerpali všechny typy replikací, které Slony1 podporuje, s výjimkou replikace prováděné napříč jednotlivými clustery, kterou zatím v praxi nepoužívám. Pokud někdo po této replikaci touží, nechť mi to napíše na email, mohu tomu věnovat jeden díl. V dalším dílu budeme probírat administraci clusteru.