slonik «EOF cluster name = customers_slave; node 3 admin conninfo = 'dbname=customers host=customers_slave3.com port=5432 user=slony password=slony_user_pass'; uninstall node (id = 3); echo 'okay'; EOF
Это нужно чтобы удалить схему, триггеры и процедуры, которые были сдублированы вместе с таблицами и структурой БД.
Инициализировать кластер не надо. Вместо этого записываем информацию о новом узле в сети:
#!/bin/sh CLUSTER=customers_rep DBNAME1=customers DBNAME3=customers HOST1=customers_master.com HOST3=customers_slave3.com PORT1=5432 PORT2=5432 SLONY_USER=slony slonik
«EOF cluster name = $CLUSTER; node 1 admin conninfo = 'dbname=$DBNAME1 host=$HOST1 port=$PORT1 user=slony password=slony_user_pass'; node 3 admin conninfo = 'dbname=$DBNAME3 host=$HOST3 port=$PORT2 user=slony password=slony_user_pass'; echo 'done adding'; store node ( id = 3, comment = 'Node 3, $HOST3' ); echo 'sored node'; store path ( server = 1, client = 3, conninfo = 'dbname=$DBNAME1 host=$HOST1 port=$PORT1 user=slony password=slony_user_pass' ); echo 'stored path'; store path ( server = 3, client = 1, conninfo = 'dbname=$DBNAME3 host=$HOST3 port=$PORT2 user=slony password=slony_user_pass' ); echo 'again'; store listen ( origin = 1, provider = 1, receiver = 3 ); store listen ( origin = 3, provider = 3, receiver = 1 ); EOF
Новый узел имеет id 3, потому что 2 уже есть и работает. Подписываем новый узел 3 на replication set:
#!/bin/sh CLUSTER=customers_rep DBNAME1=customers DBNAME3=customers HOST1=customers_master.com HOST3=customers_slave3.com PORT1=5432 PORT2=5432 SLONY_USER=slony slonik «EOF cluster name = $CLUSTER; node 1 admin conninfo = 'dbname=$DBNAME1 host=$HOST1 port=$PORT1 user=slony password=slony_user_pass'; node 3 admin conninfo = 'dbname=$DBNAME3 host=$HOST3 port=$PORT2 user=slony password=slony_user_pass'; echo'subscribing'; subscribe set ( id = 1, provider = 1, receiver = 3, forward = no); EOF
Теперь запускаем slon на новом узле, так же как и на остальных. Перезапускать slon на мастере не надо.
slony@customers_slave3$ slon customers_rep \ "dbname=customers user=slony"
Репликация должна начаться как обычно.
Устранение неисправностей
Ошибка при добавлении узла в систему репликации
Периодически, при добавлении новой машины в кластер возникает следующая ошибка: на новой ноде всё начинает жужжать и работать, имеющиеся же отваливаются с примерно следующей диагностикой:
%slon customers_rep "dbname=customers user=slony_user" CONFIG main: slon version 1.0.5 starting up CONFIG main: local node id = 3 CONFIG main: loading current cluster configuration CONFIG storeNode: no_id=1 no_comment='CustomersDB replication cluster' CONFIG storeNode: no_id=2 no_comment='Node 2, node2.example.com' CONFIG storeNode: no_id=4 no_comment='Node 4, node4.example.com' CONFIG storePath: pa_server=1 pa_client=3 pa_conninfo="dbname=customers host=mainhost.com port=5432 user=slony_user password=slony_user_pass" pa_connretry=10 CONFIG storeListen: li_origin=1 li_receiver=3 li_provider=1 CONFIG storeSet: set_id=1 set_origin=1 set_comment='CustomersDB replication set' WARN remoteWorker_wakeup: node 1 - no worker thread CONFIG storeSubscribe: sub_set=1 sub_provider=1 sub_forward='f' WARN remoteWorker_wakeup: node 1 - no worker thread CONFIG enableSubscription: sub_set=1 WARN remoteWorker_wakeup: node 1 - no worker thread CONFIG main: configuration complete - starting threads CONFIG enableNode: no_id=1 CONFIG enableNode: no_id=2 CONFIG enableNode: no_id=4 ERROR remoteWorkerThread_1: "begin transaction; set transaction isolation level serializable; lock table "_customers_rep".sl_config_lock; select "_customers_rep".enableSubscription(1, 1, 4); notify "_customers_rep_Event"; notify "_customers_rep_Confirm"; insert into "_customers_rep".sl_event (ev_origin, ev_seqno, ev_timestamp, ev_minxid, ev_maxxid, ev_xip, ev_type , ev_data1, ev_data2, ev_data3, ev_data4 ) values ('1', '219440', '2005-05-05 18:52:42.708351', '52501283', '52501292', '''52501283''', 'ENABLE_SUBSCRIPTION', '1', '1', '4', 'f'); insert into "_customers_rep". sl_confirm (con_origin, con_received, con_seqno, con_timestamp) values (1, 3, '219440', CURRENT_TIMESTAMP); commit transaction;" PGRES_FATAL_ERROR ERROR: insert or update on table "sl_subscribe" violates foreign key constraint "sl_subscribe-sl_path-ref" DETAIL: Key (sub_provider,sub_receiver)=(1,4) is not present in table "sl_path". INFO remoteListenThread_1: disconnecting from 'dbname=customers host=mainhost.com port=5432 user=slony_user password=slony_user_pass' %
Это означает что в служебной таблице _<имя кластера>.sl_path;, например _customers_rep.sl_path на уже имеющихся узлах отсутствует информация о новом узле. В данном случае, id нового узла 4, пара (1,4) в sl_path отсутствует.
Видимо, это баг Slony. Как избежать этого и последующих ручных вмешательств пока не ясно.
Чтобы это устранить, нужно выполнить на каждом из имеющихся узлов приблизительно следующий запрос (добавить путь, в данном случае (1,4)):
slony_user@masterhost$ psql -d customers -h _every_one_of_slaves -U slony customers=# insert into _customers_rep.sl_path values ('1','4','dbname=customers host=mainhost.com port=5432 user=slony_user password=slony_user_password,'10');