За да изпълним това изискване, трябва да измислим някакъв вид филтри като TRIGGER/RULEs на подчинен възел, така че да избягва препредаване на оператори DELETE и UPDATE. Тъй като имаме работа със Slony-I, той няма такъв вграден механизъм за филтриране на DML, докато ги възпроизвежда на подчинен възел, въпреки че е събрал всички събития от главния възел. (AFAIK Mysql, Oracle, SQL Server поддържат филтри ).
За да се разбере този правилен, традиционният начин на Slony-I поддържа уникалността на редовете във всички възли с основната си концепция за таблици трябва да има първични ключове. При такъв архитектурен дизайн е трудно да се изключат изразите DELETE/UPDATE, вземете пример за колона с първичен ключ „orderid“ на таблицата „orders“ има първи оператор INSERT със стойност 100 и той е репликиран като първа форма на филтриран подчинен възел. По-късно оператор DELETE, изпълнен за “orderid=100” и изтрит ред, сега, ако някой оператор INSERT или UPDATE се опита да използва “orderid=100”, тогава подчинен възел се удря с нарушение на дублиран ключ и просто прекъсва репликацията.
ERROR: duplicate key value violates unique constraint "reptest_pkey"
DETAIL: Key (id)=(2) already exists.
CONTEXT: SQL statement "INSERT INTO "public"."reptest" ("id", "name") VALUES ($1, $2);"
.....
or
....
CONTEXT: SQL statement "UPDATE ONLY "public"."reptest" SET "id" = $1 WHERE "id" = $2;"
2014-11-17 23:18:53 PST ERROR remoteWorkerThread_1: SYNC aborted
По този начин прилагането на правилото все още не е проблем, трябва да бъдете изключително предпазливи, когато то е на място. В действителност обаче прилагането на тези филтри на подчинен възел на Slony-I е много крехко, особено приложението/разработчикът трябва винаги да има предвид това, всяко дублирано въвеждане на ред от INSERT OR UPDATE може да наруши репликацията.
Тъй като правилата на DML не са възможни самостоятелно със Slony-I, можем да използваме PostgreSQL CREATE RULE…ПРИ ИЗТРИВАНЕ/НА АКТУАЛИЗИРАНЕ НЕ НАПРАВЕТЕ ВМЕСТО НИЩО и да приложим това ПРАВИЛО върху таблицата чрез ALTER TABLE…ENABLE REPLICA RULE, за да анулира израза DELETE/UPDATE. Използването на тази опция изисква много дисциплина, така че можете да сте сигурни, че вашата кандидатура и членовете на персонала наистина спазват тези правила.
За да продължите със стъпките, трябва да имате слаба настройка, в случай че трябва да настроите, можете да се обърнете към предишната ми публикация тук.
Стъпки на подчинен възел (Master DB:postgres, Slave DB:demo, Port:5432):
1. Спрете slon демони
2. Създайте правило ПРИ ИЗТРИВАНЕ и ПРИ АКТУАЛИЗИРАНЕ НЕ ВМЕСТО НИЩО
demo=# CREATE RULE void_delete AS ON DELETE TO reptest DO INSTEAD NOTHING;
CREATE RULE
demo=# CREATE RULE void_update AS ON UPDATE TO reptest DO INSTEAD NOTHING;
CREATE RULE
3. Приложете RULE върху маса
demo=# ALTER TABLE reptest ENABLE REPLICA RULE void_delete;
ALTER TABLE
demo=# ALTER TABLE reptest ENABLE REPLICA RULE void_update ;
ALTER TABLE
4. Стартирайте демони Slon
Сега можете да забележите по-долу, че UPDATE/DELETE няма влияние върху подчинения възел:
postgres=# delete from reptest where id =2;
DELETE 1
postgres=# update reptest set id=2 where id=1;
UPDATE 1
--On Master
postgres=# select * from reptest ;
id | name
----+------------
2 | A
(1 row)
--On Slave
demo=# select * from reptest ;
id | name
----+------------
1 | A
2 | C
(2 rows)
Ако инструкцията INSERT бъде изпълнена със стойност 1, това ще наруши репликацията. Забележете...!!
Не забравяйте, че има и други начини за пълно попълване на тази заявка като dblinks, тригери като BEFORE DELETE...връщане на стойност NULL от функцията, но вярвам, че най-ефективният начин би бил да използвате RULE/ENABLE REPLICA RULE, когато работите със Slony репликация.
Досега може да сте прочели много блогове за новата функция на слотове за логическо декодиране на репликация в PostgreSQL 9.4, надявам се в бъдеще да включва концепцията за филтриращи DML на Slave.
Благодарим ви за посещението.