On Fri, Sep 5, 2025 at 8:21 AM Chao Li <li.evan.c...@gmail.com> wrote:
>
> I was doing some test about logical replication a few days ago. When I tried 
> to setup a logical replication on my Macbook.
>
> The basic workflow is simple:
>
> ```
> Step 1: edit postgresql.conf and set:
>
> wal_level = logical
> max_replication_slots = 4
> max_wal_senders = 4
>
> Step 2: create two databases for pub and sub
>
> % createdb pubdb
> % createdb subdb
>
> Step 3: create a table in pubdb, and create a publication
>
> pubdb=# CREATE TABLE t (id int primary key, data text);
> CREATE TABLE
>
> pubdb=# INSERT INTO t VALUES (1, 'hello from pub');
> INSERT 0 1
>
> pubdb=# CREATE PUBLICATION mypub FOR TABLE t;
> CREATE PUBLICATION
>
> Step 4: create the same table in subdb
>
> subdb=# CREATE TABLE t (id int primary key, data text);
> CREATE TABLE
>
> Step 5: create subscription in subdb
>
> subdb=# CREATE SUBSCRIPTION mysub CONNECTION 'host=localhost dbname=pubdb' 
> PUBLICATION mypub;  <==== stuck here
> ```
>
> In step 5, "CREATE SUBSCRIPTION" got stuck. Then I found the issue had been 
> discussed with [1] in 2017, but no more effort had been spent resolving the 
> issue.
>
> Then I investigated the root cause. Feels like this is a architectural 
> problem. Because both pubdb and subdb run in the same cluster, so they share 
> the same transaction id serial.
>
> In step 5, when subdb "CREATE SUBSCRIPTION", say the transaction id is 100, 
> what the backend worker process does is like:
>
> 1) start a xact (100)
> 2) insert a tuple into pg_subscription
> 3) request pub side to create a sub slot and wait for the result
> 4) commit
>
> When the pub side receives the request to create a replication slot, it needs 
> to check no running transactions. However, xact 100 is running and waiting 
> for replication slot creation to finish. This is a deadlock, and the deadlock 
> exists only when pub and sub are in the same cluster.
>

You can avoid this problem by creating a slot first on publisher with
something like:
postgres=# select pg_create_logical_replication_slot('s1', 'pgoutput',
false, true);
 pg_create_logical_replication_slot
------------------------------------
 (s1,0/01BFF178)
(1 row)

Then while creating subscription you can use the above created slot as follows:
db1=# create subscription sub1 connection 'dbname=postgres'
publication pub1 WITH(create_slot=false, slot_name='s1');
CREATE SUBSCRIPTION

-- 
With Regards,
Amit Kapila.


Reply via email to