| From: | Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> |
|---|---|
| To: | Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com> |
| Cc: | Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Zhijie Hou <houzhijie22(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, saurabh singh <saurabh(dot)singh214(at)gmail(dot)com>, Robert Haas <robertmhaas(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org> |
| Subject: | Re: Proposal: Conflict log history table for Logical Replication |
| Date: | 2026-10-22 11:38:33 |
| Message-ID: | CAA4eK1+iFs2VpVe8C9F2xwXCfm-uTSdayZhmezN4Fq_MPEOuZw@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
On Tue, Oct 20, 2026 at 12:30 AM Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com> wrote:
>
> Also, if we don't check whether a prepared transaction exists, we
> would end up with an error if an autovacuum worker is truncating the
> CLT and the apply worker tries to acquire a lock on it. I'd rather
> expect the autovacuum worker to be interrupted in that case. If the
> apply worker waited for the lock as usual, autovacuum would give up
> truncating the table as it does for other lock waiters, but the
> conditional lock acquisition bypasses that.
>
The reason for not checking the prepared transaction is mentioned in
comments (We don't check whether prepared transactions exist before
erroring out, because one can appear while we wait. With parallel
apply, another worker of this subscription may prepare the transaction
that the command is waiting for, and we would then be stuck as
above.). Consider the following scenario:
PA-A : streamed txn S1 records a conflict -> holds RowExclusive on CLT
(S1 not prepared)
S2 : TRUNCATE CLT -> waits for S1
PA-B : streamed txn S2' records a conflict -> conditional lock fails
(TRUNCATE waiting) -> no prepared transactions -> blocking wait,
queued behind TRUNCATE
PA-A : STREAM PREPARE -> S1 becomes prepared P1 -> TRUNCATE now waits for P1
pub : COMMIT S2', then COMMIT PREPARED P1
leader: hands STREAM COMMIT to PA-B and waits for it -> PA-B is stuck
behind TRUNCATE -> COMMIT PREPARED P1 is never applied -> stall, no
ERROR
Now, to avoid the above race-condition, we can have a solution as
follows: (a) Take the lock normally on CLT with a timeout a bit above
deadlock_timeout, then ERROR if it expires. (b) Autovacuum then sees
us as a waiter and is cancelled. For the user
TRUNCATE-waiting-on-a-prepared-transaction case, the timeout turns the
hang into an ERROR and a restart.
With the above solution in place, we can also have a check for
prepared transactions instead of two_phase as the above will close the
boundary cases w.r.t parallel apply workers.
If for CLT, we agree something on the lines of above then for normal
tables, we can mention in two_phase option docs that when prepare
transactions are being replicated avoid conflicting locks like via
TRUNCATE on the table involved as that can lead to deadlock and the
only way is for user to rollback that transaction and arrange to
replicate it again by switching of two_phase.
--
With Regards,
Amit Kapila.
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Etsuro Fujita | 2026-10-22 11:47:20 | Re: Fix rescan costing of single-batch hash joins |
| Previous Message | Pavel Luzanov | 2026-10-22 11:27:03 | Re: First draft of PG 19 release notes |