When adding a node manually, you must prepare the replication stream to ensure no data is lost or duplicated. This involves a 'bookmarking' process:
- Trigger a Sync Event: Call
spock.sync_event() on the source node. This returns a Log Sequence Number (LSN) which acts as a bookmark in the replication stream. - Store the LSN: Save this LSN in a temporary table so it can be used when enabling the subscription later.
- Create a Replication Slot: On the source node, create a logical replication slot using the
spock_output plugin. This ensures changes are queued even while the subscription is disabled. - Create a Disabled Subscription: On the new node, create the subscription using
spock.sub_create() with enabled := false. This prepares the node to pull data from the source without immediately starting the sync process.
-- 1. Trigger sync event on source node (e.g., n2) and get LSN
SELECT *
FROM dblink(
'host=127.0.0.1 dbname=inventory port=5433 user=alice password=1safepassword',
'SELECT spock.sync_event()'
) AS t(sync_lsn pg_lsn);
-- 2. Store LSN in a temp table
CREATE TEMP TABLE IF NOT EXISTS temp_sync_lsns (
origin_node text PRIMARY KEY,
sync_lsn text NOT NULL
);
INSERT INTO temp_sync_lsns (origin_node, sync_lsn) VALUES ('n2', '0/1A7D1E0');
-- 3. Create replication slot on source node
SELECT *
FROM dblink(
'host=127.0.0.1 dbname=inventory port=5433 user=alice password=1safepassword',
'SELECT slot_name, lsn
FROM pg_create_logical_replication_slot(
''spk_inventory_n2_sub_n2_n4'',
''spock_output''
)'
) AS t(slot_name text, lsn pg_lsn);
-- 4. Create disabled subscription on the new node (e.g., n4)
SELECT *
FROM dblink(
'host=127.0.0.1 dbname=inventory port=5435 user=alice password=1safepassword',
'SELECT spock.sub_create(
subscription_name := ''sub_n2_n4'',
provider_dsn := ''host=127.0.0.1 dbname=inventory port=5433 user=alice password=1safepassword'',
replication_sets := ARRAY[''default'', ''default_insert_only'', ''ddl_sql''],
synchronize_structure := false,
synchronize_data := false,
forward_origins := ARRAY[]::text[],
apply_delay := ''0''::interval,
enabled := false,
force_text_transfer := false,
skip_schema := ARRAY[]::text[]
)'
) AS t(subscription_id oid);