Re: Bug in logical decoding with DDL and subtransactions

From: Bingshuai Li <lucian1412(at)outlook(dot)com>
To: "pgsql-hackers(at)lists(dot)postgresql(dot)org" <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Cc: "mark(dot)dilger(at)enterprisedb(dot)com" <mark(dot)dilger(at)enterprisedb(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "alvherre(at)kurilemu(dot)de" <alvherre(at)kurilemu(dot)de>, Alexander Lakhin <exclusion(at)gmail(dot)com>, Andrey Rachitskiy <pl0h0yp1(at)gmail(dot)com>, "a(dot)kozhemyakin(at)postgrespro(dot)ru" <a(dot)kozhemyakin(at)postgrespro(dot)ru>
Subject: Re: Bug in logical decoding with DDL and subtransactions
Date: 2026-09-17 08:33:08
Message-ID: ME0P300MB0953FB8C1B9731C5C28EEC3EC6B82@ME0P300MB0953.AUSP300.PROD.OUTLOOK.COM
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi Alexander,

Thanks for the data point. These failures are exactly the assertion
analyzed in this thread, and the failing statement is the decode call
right after the ddl test's own "DDL in aborted subtransactions"
section (contrib/test_decoding/sql/ddl.sql):

CREATE TABLE tr_sub_ddl(data int);
BEGIN;
SAVEPOINT a;
ALTER TABLE tr_sub_ddl ALTER COLUMN data TYPE text;
INSERT INTO tr_sub_ddl VALUES ('blah-blah');
ROLLBACK TO SAVEPOINT a;
ALTER TABLE tr_sub_ddl ALTER COLUMN data TYPE bigint;
INSERT INTO tr_sub_ddl VALUES(43);
COMMIT;

That is the same shape as the BUG #19555 reproducer, and the lines
missing from the ddl.out diff are everything after the backend died.

The failure is inherently layout-dependent: it needs on-access
pruning to free the rolled-back subtransaction's catalog line
pointer and a later catalog insert to reuse that tid. Presumably
prion's force-release configuration (RELCACHE_FORCE_RELEASE,
CATCACHE_FORCE_RELEASE) makes that far more likely than on other
animals -- two hits in one evening supports that.

The v4 patch posted on 2026-08-15 [1] fixes exactly this path: it
removes the aborted subtransaction's tuplecid entries in
ReorderBufferAbort(), so no stale (relfilelocator, tid) mapping
remains to collide with a reused tid. The regression test added by
v4 reproduces this crash within a handful of iterations on
unpatched assert builds and always passes with the patch.

I re-checked v4 against current master (be00f041a33) today: it
still applies cleanly, and no upstream commit has touched the
tuplecid code paths since it was posted, so the verification matrix
from the v4 mail (master and REL_19_STABLE, assert and non-assert,
both build systems) still stands.

With the buildfarm now red on HEAD and PostgreSQL 19 GA
approaching, could a committer please take a look at v4? The two
points where I would most appreciate judgement are unchanged from
my August 27 mail: the restart_lsn invariant (section 2 of the v4
mail), and whether the O(N) abort-time cleanup is acceptable to
backpatch. I also believe this strengthens the case for tracking
BUG #19555 as a PostgreSQL 19 open item. I'm happy to prepare a
REL_19_STABLE version of the patch if that would help.

[1] https://www.postgresql.org/message-id/SY8P300MB0570D533D4F6B47B804C7D57C6D92%40SY8P300MB0570.AUSP300.PROD.OUTLOOK.COM

Thanks,
Bingshuai Li

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Nisha Moond 2026-09-17 08:34:42 Re: Distinguish publication exclusions in object addresses
Previous Message David Geier 2026-09-17 08:13:28 Re: Use correct collation in pg_trgm