agora inbox for [email protected]
help / color / mirror / Atom feedRe: Error message inconsistency
1934+ messages / 7 participants
[nested] [flat]
* Re: Error message inconsistency
@ 2020-01-06 13:00 Mahendra Singh Thalor <[email protected]>
0 siblings, 2 replies; 1934+ messages in thread
From: Mahendra Singh Thalor @ 2020-01-06 13:00 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Alvaro Herrera <[email protected]>; Simon Riggs <[email protected]>; Fabrízio Mello <[email protected]>; PostgreSQL Hackers <[email protected]>
On Sat, 6 Jul 2019 at 09:53, Amit Kapila <[email protected]> wrote:
>
> On Mon, Jul 1, 2019 at 10:05 PM Alvaro Herrera <[email protected]>
wrote:
> >
> > Do we have an actual patch here?
> >
>
> We have a patch, but it needs some more work like finding similar
> places and change all of them at the same time and then change the
> tests to adapt the same.
>
Hi all,
Based on above discussion, I tried to find out all the places where we need
to change error for "not null constraint". As Amit Kapila pointed out 1
place, I changed the error and adding modified patch.
*What does this patch? *
Before this patch, to display error of "not-null constraint", we were not
displaying relation name in some cases so attached patch is adding relation
name with the "not-null constraint" error in 2 places. I didn't changed out
files of test suite as we haven't finalized error messages.
I verified Robert's point of for partition tables also. With the error, we
are adding relation name of "child table" and i think, it is correct.
Please review attached patch and let me know feedback.
Thanks and Regards
Mahendra Singh Thalor
EnterpriseDB: http://www.enterprisedb.com
Attachments:
[application/octet-stream] rationalize_constraint_error_messages_v2.patch (1.5K, ../../CAKYtNAqRSkbV+scUerHu3vwaQHm1rhOPKth5GJcOUxT6ZmBf2Q@mail.gmail.com/3-rationalize_constraint_error_messages_v2.patch)
download | inline diff:
commit 0d6619694bb4c20b9f006d5f71af61d5ddb4c2d7
Author: Mahendra Singh Thalor <[email protected]>
Date: Mon Jan 6 18:14:40 2020 +0530
Added table name in "not-null constrain" error
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 1c4394a..c683673 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -5007,8 +5007,9 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
ereport(ERROR,
(errcode(ERRCODE_NOT_NULL_VIOLATION),
- errmsg("column \"%s\" contains null values",
- NameStr(attr->attname)),
+ errmsg("column \"%s\" of relation \"%s\" contains null values",
+ NameStr(attr->attname),
+ RelationGetRelationName(oldrel)),
errtablecol(oldrel, attn + 1)));
}
}
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 4181a7e..f787ead 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -1957,8 +1957,9 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
ereport(ERROR,
(errcode(ERRCODE_NOT_NULL_VIOLATION),
- errmsg("null value in column \"%s\" violates not-null constraint",
- NameStr(att->attname)),
+ errmsg("null value in column \"%s\" of relation \"%s\" violates not-null constraint",
+ NameStr(att->attname),
+ RelationGetRelationName(orig_rel)),
val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
errtablecol(orig_rel, attrChk)));
}
^ permalink raw reply [nested|flat] 1934+ messages in thread
* Re: Error message inconsistency
@ 2020-01-09 12:12 MBeena Emerson <[email protected]>
parent: Mahendra Singh Thalor <[email protected]>
1 sibling, 1 reply; 1934+ messages in thread
From: MBeena Emerson @ 2020-01-09 12:12 UTC (permalink / raw)
To: Mahendra Singh Thalor <[email protected]>; +Cc: Amit Kapila <[email protected]>; Alvaro Herrera <[email protected]>; Simon Riggs <[email protected]>; Fabrízio Mello <[email protected]>; PostgreSQL Hackers <[email protected]>
Hi Mahendra,
Thanks for the patch.
I am not sure but maybe the relation name should also be added to the
following test case?
create table t4 (id int);
insert into t4 values (1);
ALTER TABLE t4 ADD CONSTRAINT c1 CHECK (id > 10) NOT VALID; -- succeeds
ALTER TABLE t4 VALIDATE CONSTRAINT c1;
*ERROR: check constraint "c1" is violated by some row*
On Mon, 6 Jan 2020 at 18:31, Mahendra Singh Thalor <[email protected]>
wrote:
> On Sat, 6 Jul 2019 at 09:53, Amit Kapila <[email protected]> wrote:
> >
> > On Mon, Jul 1, 2019 at 10:05 PM Alvaro Herrera <[email protected]>
> wrote:
> > >
> > > Do we have an actual patch here?
> > >
> >
> > We have a patch, but it needs some more work like finding similar
> > places and change all of them at the same time and then change the
> > tests to adapt the same.
> >
>
> Hi all,
> Based on above discussion, I tried to find out all the places where we
> need to change error for "not null constraint". As Amit Kapila pointed out
> 1 place, I changed the error and adding modified patch.
>
>
> *What does this patch? *
> Before this patch, to display error of "not-null constraint", we were not
> displaying relation name in some cases so attached patch is adding relation
> name with the "not-null constraint" error in 2 places. I didn't changed out
> files of test suite as we haven't finalized error messages.
>
> I verified Robert's point of for partition tables also. With the error, we
> are adding relation name of "child table" and i think, it is correct.
>
> Please review attached patch and let me know feedback.
>
> Thanks and Regards
> Mahendra Singh Thalor
> EnterpriseDB: http://www.enterprisedb.com
>
--
--
M Beena Emerson
^ permalink raw reply [nested|flat] 1934+ messages in thread
* Re: Error message inconsistency
@ 2020-01-21 05:19 Amit Kapila <[email protected]>
parent: MBeena Emerson <[email protected]>
0 siblings, 1 reply; 1934+ messages in thread
From: Amit Kapila @ 2020-01-21 05:19 UTC (permalink / raw)
To: MBeena Emerson <[email protected]>; +Cc: Mahendra Singh Thalor <[email protected]>; Alvaro Herrera <[email protected]>; Simon Riggs <[email protected]>; Fabrízio Mello <[email protected]>; PostgreSQL Hackers <[email protected]>
On Thu, Jan 9, 2020 at 5:42 PM MBeena Emerson <[email protected]> wrote:
>
Hi Beena,
It is better to reply inline.
> Hi Mahendra,
>
> Thanks for the patch.
> I am not sure but maybe the relation name should also be added to the following test case?
>
> create table t4 (id int);
> insert into t4 values (1);
> ALTER TABLE t4 ADD CONSTRAINT c1 CHECK (id > 10) NOT VALID; -- succeeds
> ALTER TABLE t4 VALIDATE CONSTRAINT c1;
> ERROR: check constraint "c1" is violated by some row
>
I see that in this case, we are using errtableconstraint which should
set table/schema name, but then that doesn't seem to be used. Can we
explore it a bit from that angle?
--
With Regards,
Amit Kapila.
EnterpriseDB: http://www.enterprisedb.com
^ permalink raw reply [nested|flat] 1934+ messages in thread
* Re: Error message inconsistency
@ 2020-01-21 05:21 Amit Kapila <[email protected]>
parent: Mahendra Singh Thalor <[email protected]>
1 sibling, 1 reply; 1934+ messages in thread
From: Amit Kapila @ 2020-01-21 05:21 UTC (permalink / raw)
To: Mahendra Singh Thalor <[email protected]>; +Cc: Alvaro Herrera <[email protected]>; Simon Riggs <[email protected]>; Fabrízio Mello <[email protected]>; PostgreSQL Hackers <[email protected]>
On Mon, Jan 6, 2020 at 6:31 PM Mahendra Singh Thalor <[email protected]> wrote:
>
> On Sat, 6 Jul 2019 at 09:53, Amit Kapila <[email protected]> wrote:
> >
> > On Mon, Jul 1, 2019 at 10:05 PM Alvaro Herrera <[email protected]> wrote:
> > >
> > > Do we have an actual patch here?
> > >
> >
> > We have a patch, but it needs some more work like finding similar
> > places and change all of them at the same time and then change the
> > tests to adapt the same.
> >
>
> Hi all,
> Based on above discussion, I tried to find out all the places where we need to change error for "not null constraint". As Amit Kapila pointed out 1 place, I changed the error and adding modified patch.
>
It seems you have not used the two error codes
(ERRCODE_NOT_NULL_VIOLATION and ERRCODE_CHECK_VIOLATION) pointed by me
above.
> What does this patch?
> Before this patch, to display error of "not-null constraint", we were not displaying relation name in some cases so attached patch is adding relation name with the "not-null constraint" error in 2 places. I didn't changed out files of test suite as we haven't finalized error messages.
>
> I verified Robert's point of for partition tables also. With the error, we are adding relation name of "child table" and i think, it is correct.
>
Can you show the same with the help of an example?
--
With Regards,
Amit Kapila.
EnterpriseDB: http://www.enterprisedb.com
^ permalink raw reply [nested|flat] 1934+ messages in thread
* Re: Error message inconsistency
@ 2020-01-21 05:37 MBeena Emerson <[email protected]>
parent: Amit Kapila <[email protected]>
0 siblings, 1 reply; 1934+ messages in thread
From: MBeena Emerson @ 2020-01-21 05:37 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Mahendra Singh Thalor <[email protected]>; Alvaro Herrera <[email protected]>; Simon Riggs <[email protected]>; Fabrízio Mello <[email protected]>; PostgreSQL Hackers <[email protected]>
Hi Amit,
On Tue, 21 Jan 2020 at 10:49, Amit Kapila <[email protected]> wrote:
> On Thu, Jan 9, 2020 at 5:42 PM MBeena Emerson <[email protected]>
> wrote:
> >
>
> Hi Beena,
>
> It is better to reply inline.
>
> > Hi Mahendra,
> >
> > Thanks for the patch.
> > I am not sure but maybe the relation name should also be added to the
> following test case?
> >
> > create table t4 (id int);
> > insert into t4 values (1);
> > ALTER TABLE t4 ADD CONSTRAINT c1 CHECK (id > 10) NOT VALID; -- succeeds
> > ALTER TABLE t4 VALIDATE CONSTRAINT c1;
> > ERROR: check constraint "c1" is violated by some row
> >
>
> I see that in this case, we are using errtableconstraint which should
> set table/schema name, but then that doesn't seem to be used. Can we
> explore it a bit from that angle?
>
The usage of the function errtableconstraint seems only to set the
schema_name table_name constraint_name internally and not for display
purposes. As seen in the following two cases where the relation name is
displayed using RelationGetRelationName and errtableconstraint is called as
part of errcode parameter not errmsg.
ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION),
errmsg("new row for relation \"%s\" violates check
constraint \"%s\"",
RelationGetRelationName(orig_rel), failed),
val_desc ? errdetail("Failing row contains %s.",
val_desc) : 0,
errtableconstraint(orig_rel, failed)));
ereport(ERROR,
(errcode(ERRCODE_UNIQUE_VIOLATION),
errmsg("duplicate key value violates
unique constraint \"%s\"",
RelationGetRelationName(rel)),
key_desc ? errdetail("Key %s already
exists.",
key_desc) : 0,
errtableconstraint(heapRel,
RelationGetRelationName(rel))));
--
M Beena Emerson
EnterpriseDB: http://www.enterprisedb.com
^ permalink raw reply [nested|flat] 1934+ messages in thread
* Re: Error message inconsistency
@ 2020-01-21 14:39 Alvaro Herrera <[email protected]>
parent: MBeena Emerson <[email protected]>
0 siblings, 1 reply; 1934+ messages in thread
From: Alvaro Herrera @ 2020-01-21 14:39 UTC (permalink / raw)
To: MBeena Emerson <[email protected]>; +Cc: Amit Kapila <[email protected]>; Mahendra Singh Thalor <[email protected]>; Simon Riggs <[email protected]>; Fabrízio Mello <[email protected]>; PostgreSQL Hackers <[email protected]>
On 2020-Jan-21, MBeena Emerson wrote:
> The usage of the function errtableconstraint seems only to set the
> schema_name table_name constraint_name internally and not for display
> purposes. As seen in the following two cases where the relation name is
> displayed using RelationGetRelationName and errtableconstraint is called as
> part of errcode parameter not errmsg.
You can see those fields by raising the log verbosity; it's a
client-side thing. For example, in psql you can use
\set VERBOSITY verbose
In psql you can also use \errverbose after an error to print those
fields.
--
Álvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
^ permalink raw reply [nested|flat] 1934+ messages in thread
* Re: Error message inconsistency
@ 2020-01-22 07:39 Mahendra Singh Thalor <[email protected]>
parent: Alvaro Herrera <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Mahendra Singh Thalor @ 2020-01-22 07:39 UTC (permalink / raw)
To: Alvaro Herrera <[email protected]>; +Cc: MBeena Emerson <[email protected]>; Amit Kapila <[email protected]>; Simon Riggs <[email protected]>; Fabrízio Mello <[email protected]>; PostgreSQL Hackers <[email protected]>
On Tue, 21 Jan 2020 at 20:09, Alvaro Herrera <[email protected]> wrote:
>
> On 2020-Jan-21, MBeena Emerson wrote:
>
> > The usage of the function errtableconstraint seems only to set the
> > schema_name table_name constraint_name internally and not for display
> > purposes. As seen in the following two cases where the relation name is
> > displayed using RelationGetRelationName and errtableconstraint is called as
> > part of errcode parameter not errmsg.
>
> You can see those fields by raising the log verbosity; it's a
> client-side thing. For example, in psql you can use
> \set VERBOSITY verbose
>
> In psql you can also use \errverbose after an error to print those
> fields.
Thanks for the explanation.
--
Thanks and Regards
Mahendra Singh Thalor
EnterpriseDB: http://www.enterprisedb.com
^ permalink raw reply [nested|flat] 1934+ messages in thread
* Re: Error message inconsistency
@ 2020-01-22 07:55 Mahendra Singh Thalor <[email protected]>
parent: Amit Kapila <[email protected]>
0 siblings, 1 reply; 1934+ messages in thread
From: Mahendra Singh Thalor @ 2020-01-22 07:55 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Alvaro Herrera <[email protected]>; Simon Riggs <[email protected]>; Fabrízio Mello <[email protected]>; PostgreSQL Hackers <[email protected]>
On Tue, 21 Jan 2020 at 10:51, Amit Kapila <[email protected]> wrote:
>
> On Mon, Jan 6, 2020 at 6:31 PM Mahendra Singh Thalor <[email protected]>
wrote:
> >
> > On Sat, 6 Jul 2019 at 09:53, Amit Kapila <[email protected]>
wrote:
> > >
> > > On Mon, Jul 1, 2019 at 10:05 PM Alvaro Herrera <
[email protected]> wrote:
> > > >
> > > > Do we have an actual patch here?
> > > >
> > >
> > > We have a patch, but it needs some more work like finding similar
> > > places and change all of them at the same time and then change the
> > > tests to adapt the same.
> > >
> >
> > Hi all,
> > Based on above discussion, I tried to find out all the places where we
need to change error for "not null constraint". As Amit Kapila pointed out
1 place, I changed the error and adding modified patch.
> >
>
> It seems you have not used the two error codes
> (ERRCODE_NOT_NULL_VIOLATION and ERRCODE_CHECK_VIOLATION) pointed by me
> above.
Thanks Amit and Beena for reviewing patch.
Yes, you are correct. I searched using error messages not error code. That
was my mistake. Now, I grepped using above error codes and found that
these error codes are used in 19 places. Below is the code parts of 19
places.
1. src/backend/utils/adt/domains.c
- 146 if (isnull)
- 147 ereport(ERROR,
- 148 (errcode(ERRCODE_NOT_NULL_VIOLATION),
- 149 errmsg("domain %s does not allow null
values",
- 150
format_type_be(my_extra->domain_type)),
- 151 errdatatype(my_extra->domain_type)));
- 152 break;
I think, above error is for domain, so there is no need to add anything in
error message.
-----------------------------------------------------------------------------------------------------
2. src/backend/utils/adt/domains.c
- 181 if (!ExecCheck(con->check_exprstate,
econtext))
- 182 ereport(ERROR,
- 183 (errcode(ERRCODE_CHECK_VIOLATION),
- 184 errmsg("value for domain %s
violates check constraint \"%s\"",
- 185
format_type_be(my_extra->domain_type),
- 186 con->name),
- 187
errdomainconstraint(my_extra->domain_type,
- 188 con->name)));
I think, above error is for domain, so there is no need to add anything in
error message.
-----------------------------------------------------------------------------------------------------
3. src/backend/partitioning/partbounds.c
- 1330 if (part_rel->rd_rel->relkind ==
RELKIND_FOREIGN_TABLE)
- 1331 ereport(WARNING,
- 1332 (errcode(ERRCODE_CHECK_VIOLATION),
- 1333 errmsg("skipped scanning foreign table
\"%s\" which is a partition of default partition \"%s\"",
- 1334 RelationGetRelationName(part_rel),
- 1335
RelationGetRelationName(default_rel))));
Relation name is already appended in error messgae.
-----------------------------------------------------------------------------------------------------
4. src/backend/partitioning/partbounds.c
- 1363 if (!ExecCheck(partqualstate, econtext))
- 1364 ereport(ERROR,
- 1365 (errcode(ERRCODE_CHECK_VIOLATION),
- 1366 errmsg("updated partition constraint for
default partition \"%s\" would be violated by some row",
- 1367
RelationGetRelationName(default_rel))));
Relation name is already appended in error messgae.
-----------------------------------------------------------------------------------------------------
5. src/backend/executor/execPartition.c
- 342 ereport(ERROR,
- 343 (errcode(ERRCODE_CHECK_VIOLATION),
- 344 errmsg("no partition of relation \"%s\"
found for row",
- 345 RelationGetRelationName(rel)),
- 346 val_desc ?
- 347 errdetail("Partition key of the failing row
contains %s.",
- 348 val_desc) : 0));
Relation name is already appended in error messgae.
-----------------------------------------------------------------------------------------------------
6. src/backend/executor/execMain.c
- 1877 ereport(ERROR,
- 1878 (errcode(ERRCODE_CHECK_VIOLATION),
- 1879 errmsg("new row for relation \"%s\" violates
partition constraint",
- 1880
RelationGetRelationName(resultRelInfo->ri_RelationDesc)),
- 1881 val_desc ? errdetail("Failing row contains %s.",
val_desc) : 0));
Relation name is already appended in error messgae.
-----------------------------------------------------------------------------------------------------
7. src/backend/executor/execMain.c
- 1958 ereport(ERROR,
- 1959 (errcode(ERRCODE_NOT_NULL_VIOLATION),
- 1960 errmsg("null value in column \"%s\"
violates not-null constraint",
- 1961 NameStr(att->attname)),
- 1962 val_desc ? errdetail("Failing row
contains %s.", val_desc) : 0,
- 1963 errtablecol(orig_rel, attrChk)));
Added relation name for this error. This can be verified by below example:
*Ex:*
CREATE TABLE test (a int PRIMARY KEY, b int GENERATED ALWAYS AS (nullif(a,
0)) STORED NOT NULL);
INSERT INTO test (a) VALUES (1);
INSERT INTO test (a) VALUES (0);
*Without patch:*
ERROR: null value in column "b" violates not-null constraint
DETAIL: Failing row contains (0, null).
*With patch:*
ERROR: null value in column "b" of relation "test" violates not-null
constraint
DETAIL: Failing row contains (0, null).
-----------------------------------------------------------------------------------------------------
8. src/backend/executor/execMain.c
- 2006 ereport(ERROR,
- 2007 (errcode(ERRCODE_CHECK_VIOLATION),
- 2008 errmsg("new row for relation \"%s\" violates
check constraint \"%s\"",
- 2009 RelationGetRelationName(orig_rel),
failed),
- 2010 val_desc ? errdetail("Failing row contains
%s.", val_desc) : 0,
- 2011 errtableconstraint(orig_rel, failed)));
Relation name is already appended in error messgae.
-----------------------------------------------------------------------------------------------------
9. src/backend/executor/execExprInterp.c
- 3600 ereport(ERROR,
- 3601 (errcode(ERRCODE_NOT_NULL_VIOLATION),
- 3602 errmsg("domain %s does not allow null values",
- 3603
format_type_be(op->d.domaincheck.resulttype)),
- 3604 errdatatype(op->d.domaincheck.resulttype)));
I think, above error is for domain, so there is no need to add anything in
error message.
-----------------------------------------------------------------------------------------------------
10. src/backend/executor/execExprInterp.c
- 3615 ereport(ERROR,
- 3616 (errcode(ERRCODE_CHECK_VIOLATION),
- 3617 errmsg("value for domain %s violates check
constraint \"%s\"",
- 3618
format_type_be(op->d.domaincheck.resulttype),
- 3619 op->d.domaincheck.constraintname),
- 3620 errdomainconstraint(op->d.domaincheck.resulttype,
- 3621
op->d.domaincheck.constraintname)));
I think, above error is for domain, so there is no need to add anything in
error message.
-----------------------------------------------------------------------------------------------------
11. src/backend/commands/tablecmds.c
- 5273 ereport(ERROR,
- 5274 (errcode(ERRCODE_NOT_NULL_VIOLATION),
- 5275 errmsg("column \"%s\" contains null
values",
- 5276 NameStr(attr->attname)),
- 5277 errtablecol(oldrel, attn + 1)));
Added relation name for this error. This can be verified by below example:
*Ex:*
CREATE TABLE test (a int);
INSERT INTO test VALUES (0), (1);
ALTER TABLE test ADD COLUMN b int NOT NULL, ALTER COLUMN b ADD GENERATED
ALWAYS AS IDENTITY;
*Without patch:*
ERROR: column "b" contains null values
*With patch*:
ERROR: column "b" of relation "test" contains null values
-----------------------------------------------------------------------------------------------------
12. src/backend/commands/tablecmds.c
- 5288 if (!ExecCheck(con->qualstate,
econtext))
- 5289 ereport(ERROR,
- 5290
(errcode(ERRCODE_CHECK_VIOLATION),
- 5291 errmsg("check constraint
\"%s\" is violated by some row",
- 5292 con->name),
- 5293 errtableconstraint(oldrel,
con->name)));
Added relation name for this error. This can be verified by below example:
*Ex:*
CREATE TABLE test (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2)
STORED);
INSERT INTO test (a) VALUES (10), (30);
ALTER TABLE test ADD CHECK (b < 50);
*Without patch:*
ERROR: check constraint "test_b_check" is violated by some row
*With patch:*
ERROR: check constraint "test_b_check" of relation "test" is violated by
some row
-----------------------------------------------------------------------------------------------------
13. src/backend/commands/tablecmds.c
- 5306 if (tab->validate_default)
- 5307 ereport(ERROR,
- 5308 (errcode(ERRCODE_CHECK_VIOLATION),
- 5309 errmsg("updated partition
constraint for default partition would be violated by some row")));
Added relation name for this error. This can be verified by below example:
*Ex:*
CREATE TABLE list_parted ( a int, b char ) PARTITION BY LIST (a);
CREATE TABLE list_parted_def PARTITION OF list_parted DEFAULT;
INSERT INTO list_parted_def VALUES (11, 'z');
CREATE TABLE part_1 (LIKE list_parted);
ALTER TABLE list_parted ATTACH PARTITION part_1 FOR VALUES IN (11);
*Without patch:*
ERROR: updated partition constraint for default partition would be
violated by some row
*With patch:*
ERROR: updated partition constraint for default partition
"list_parted_def" would be violated by some row
-----------------------------------------------------------------------------------------------------
14. src/backend/commands/tablecmds.c
- 5310 else
- 5311 ereport(ERROR,
- 5312 (errcode(ERRCODE_CHECK_VIOLATION),
- 5313 errmsg("partition constraint is
violated by some row")));
Added relation name for this error. This can be verified by below example:
*Ex:*
CREATE TABLE list_parted (a int,b char)PARTITION BY LIST (a);
CREATE TABLE part_1 (LIKE list_parted);
INSERT INTO part_1 VALUES (3, 'a');
ALTER TABLE list_parted ATTACH PARTITION part_1 FOR VALUES IN (2);
*Without patch:*
ERROR: partition constraint is violated by some row
*With patch:*
ERROR: partition constraint "part_1" is violated by some row
---------------------------------------------------------------------------
15. src/backend/commands/tablecmds.c
- 10141 ereport(ERROR,
- 10142 (errcode(ERRCODE_CHECK_VIOLATION),
- 10143 errmsg("check constraint \"%s\" is violated
by some row",
- 10144 NameStr(constrForm->conname)),
- 10145 errtableconstraint(rel,
NameStr(constrForm->conname))));
Added relation name for this error. This can be verified by below example:
*Ex:*
CREATE TABLE test (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2)
STORED);
INSERT INTO test (a) VALUES (10), (30);
ALTER TABLE test ADD CONSTRAINT chk CHECK (b < 50) NOT VALID;
ALTER TABLE test VALIDATE CONSTRAINT chk;
*Without patch:*
ERROR: check constraint "chk" is violated by some row
*With patch:*
ERROR: check constraint "chk" of relation "test" is violated by some row
-----------------------------------------------------------------------------------------------------
16. src/backend/commands/typecmds.c
- 2396 ereport(ERROR,
- 2397
(errcode(ERRCODE_NOT_NULL_VIOLATION),
- 2398 errmsg("column \"%s\" of table
\"%s\" contains null values",
- 2399 NameStr(attr->attname),
- 2400
RelationGetRelationName(testrel)),
- 2401 errtablecol(testrel, attnum)));
Relation name is already appended in error messgae.
-----------------------------------------------------------------------------------------------------
17. src/backend/commands/typecmds.c
- 2824 ereport(ERROR,
- 2825 (errcode(ERRCODE_CHECK_VIOLATION),
- 2826 errmsg("column \"%s\" of table
\"%s\" contains values that violate the new constraint",
- 2827 NameStr(attr->attname),
- 2828
RelationGetRelationName(testrel)),
- 2829 errtablecol(testrel, attnum)));
Relation name is already appended in error messgae.
-----------------------------------------------------------------------------------------------------
18. src/backend/commands/typecmds.c
- 2396 ereport(ERROR,
- 2397
(errcode(ERRCODE_NOT_NULL_VIOLATION),
- 2398 errmsg("column \"%s\" of table
\"%s\" contains null values",
- 2399 NameStr(attr->attname),
- 2400
RelationGetRelationName(testrel)),
- 2401 errtablecol(testrel, attnum)));
Relation name is already appended in error messgae.
-----------------------------------------------------------------------------------------------------
19. src/backend/commands/typecmds.c
- 2824 ereport(ERROR,
- 2825 (errcode(ERRCODE_CHECK_VIOLATION),
- 2826 errmsg("column \"%s\" of table
\"%s\" contains values that violate the new constraint",
- 2827 NameStr(attr->attname),
- 2828
RelationGetRelationName(testrel)),
- 2829 errtablecol(testrel, attnum)))
Relation name is already appended in error messgae.
-----------------------------------------------------------------------------------------------------
>
> > What does this patch?
> > Before this patch, to display error of "not-null constraint", we were
not displaying relation name in some cases so attached patch is adding
relation name with the "not-null constraint" error in 2 places. I didn't
changed out files of test suite as we haven't finalized error messages.
> >
> > I verified Robert's point of for partition tables also. With the error,
we are adding relation name of "child table" and i think, it is correct.
> >
>
> Can you show the same with the help of an example?
Okay. Below is the example:
create table parent (a int, b int not null) partition by range (a);
create table ch1 partition of parent for values from ( 10 ) to (20);
postgres=# insert into parent values (9);
ERROR: no partition of relation "parent" found for row
DETAIL: Partition key of the failing row contains (a) = (9).
postgres=# insert into parent values (11);
*ERROR: null value in column "b" of relation "ch1" violates not-null
constraint*
DETAIL: Failing row contains (11, null).
Attaching a patch for review. In this patch, total 6 places I added
relation name in error message and verifyed same with above mentioned
examples.
Please review attahced patch and let me know your feedback. I haven't
modifed .out files because we haven't finalied patch.
--
Thanks and Regards
Mahendra Singh Thalor
EnterpriseDB: http://www.enterprisedb.com
Attachments:
[application/octet-stream] rationalize_constraint_error_messages_v3.patch (3.3K, ../../CAKYtNAqYgdh1JhZ51cdEVHvg=1FzTeos3TQidHo8K2FnoNMBDA@mail.gmail.com/3-rationalize_constraint_error_messages_v3.patch)
download | inline diff:
commit 27ede32cd35afc2872152c9edcd91f05feda1fe0
Author: Mahendra Singh Thalor <[email protected]>
Date: Wed Jan 22 09:47:44 2020 +0530
fixed error message inconsistancy
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 30b72b6..b0bed6a 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -5272,8 +5272,9 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
ereport(ERROR,
(errcode(ERRCODE_NOT_NULL_VIOLATION),
- errmsg("column \"%s\" contains null values",
- NameStr(attr->attname)),
+ errmsg("column \"%s\" of relation \"%s\" contains null values",
+ NameStr(attr->attname),
+ RelationGetRelationName(oldrel)),
errtablecol(oldrel, attn + 1)));
}
}
@@ -5288,8 +5289,9 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
if (!ExecCheck(con->qualstate, econtext))
ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION),
- errmsg("check constraint \"%s\" is violated by some row",
- con->name),
+ errmsg("check constraint \"%s\" of relation \"%s\" is violated by some row",
+ con->name,
+ RelationGetRelationName(oldrel)),
errtableconstraint(oldrel, con->name)));
break;
case CONSTR_FOREIGN:
@@ -5306,11 +5308,13 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
if (tab->validate_default)
ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION),
- errmsg("updated partition constraint for default partition would be violated by some row")));
+ errmsg("updated partition constraint for default partition \"%s\" would be violated by some row",
+ RelationGetRelationName(oldrel))));
else
ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION),
- errmsg("partition constraint is violated by some row")));
+ errmsg("partition constraint \"%s\" is violated by some row",
+ RelationGetRelationName(oldrel))));
}
/* Write the tuple out to the new relation */
@@ -10140,8 +10144,9 @@ validateCheckConstraint(Relation rel, HeapTuple constrtup)
if (!ExecCheck(exprstate, econtext))
ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION),
- errmsg("check constraint \"%s\" is violated by some row",
- NameStr(constrForm->conname)),
+ errmsg("check constraint \"%s\" of relation \"%s\" is violated by some row",
+ NameStr(constrForm->conname),
+ RelationGetRelationName(rel)),
errtableconstraint(rel, NameStr(constrForm->conname))));
ResetExprContext(econtext);
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index b03e02a..3a9ce99 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -1957,8 +1957,9 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
ereport(ERROR,
(errcode(ERRCODE_NOT_NULL_VIOLATION),
- errmsg("null value in column \"%s\" violates not-null constraint",
- NameStr(att->attname)),
+ errmsg("null value in column \"%s\" of relation \"%s\" violates not-null constraint",
+ NameStr(att->attname),
+ RelationGetRelationName(orig_rel)),
val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
errtablecol(orig_rel, attrChk)));
}
^ permalink raw reply [nested|flat] 1934+ messages in thread
* Re: Error message inconsistency
@ 2020-01-22 09:53 MBeena Emerson <[email protected]>
parent: Mahendra Singh Thalor <[email protected]>
0 siblings, 2 replies; 1934+ messages in thread
From: MBeena Emerson @ 2020-01-22 09:53 UTC (permalink / raw)
To: Mahendra Singh Thalor <[email protected]>; +Cc: Amit Kapila <[email protected]>; Alvaro Herrera <[email protected]>; Simon Riggs <[email protected]>; Fabrízio Mello <[email protected]>; PostgreSQL Hackers <[email protected]>
Hi Mahendra,
Thanks for working on this.
On Wed, 22 Jan 2020 at 13:26, Mahendra Singh Thalor <[email protected]> wrote:
>
> On Tue, 21 Jan 2020 at 10:51, Amit Kapila <[email protected]> wrote:
> >
> > On Mon, Jan 6, 2020 at 6:31 PM Mahendra Singh Thalor <[email protected]> wrote:
> > >
> > > On Sat, 6 Jul 2019 at 09:53, Amit Kapila <[email protected]> wrote:
> > > >
> > > > On Mon, Jul 1, 2019 at 10:05 PM Alvaro Herrera <[email protected]> wrote:
> > > > >
> > > > > Do we have an actual patch here?
> > > > >
> > > >
> > > > We have a patch, but it needs some more work like finding similar
> > > > places and change all of them at the same time and then change the
> > > > tests to adapt the same.
> > > >
> > >
> > > Hi all,
> > > Based on above discussion, I tried to find out all the places where we need to change error for "not null constraint". As Amit Kapila pointed out 1 place, I changed the error and adding modified patch.
> > >
> >
> > It seems you have not used the two error codes
> > (ERRCODE_NOT_NULL_VIOLATION and ERRCODE_CHECK_VIOLATION) pointed by me
> > above.
>
> Thanks Amit and Beena for reviewing patch.
>
> Yes, you are correct. I searched using error messages not error code. That was my mistake. Now, I grepped using above error codes and found that these error codes are used in 19 places. Below is the code parts of 19 places.
>
> 1. src/backend/utils/adt/domains.c
>
> 146 if (isnull)
> 147 ereport(ERROR,
> 148 (errcode(ERRCODE_NOT_NULL_VIOLATION),
> 149 errmsg("domain %s does not allow null values",
> 150 format_type_be(my_extra->domain_type)),
> 151 errdatatype(my_extra->domain_type)));
> 152 break;
>
> I think, above error is for domain, so there is no need to add anything in error message.
> -----------------------------------------------------------------------------------------------------
> 2. src/backend/utils/adt/domains.c
>
> 181 if (!ExecCheck(con->check_exprstate, econtext))
> 182 ereport(ERROR,
> 183 (errcode(ERRCODE_CHECK_VIOLATION),
> 184 errmsg("value for domain %s violates check constraint \"%s\"",
> 185 format_type_be(my_extra->domain_type),
> 186 con->name),
> 187 errdomainconstraint(my_extra->domain_type,
> 188 con->name)));
>
> I think, above error is for domain, so there is no need to add anything in error message.
> -----------------------------------------------------------------------------------------------------
> 3. src/backend/partitioning/partbounds.c
>
> 1330 if (part_rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
> 1331 ereport(WARNING,
> 1332 (errcode(ERRCODE_CHECK_VIOLATION),
> 1333 errmsg("skipped scanning foreign table \"%s\" which is a partition of default partition \"%s\"",
> 1334 RelationGetRelationName(part_rel),
> 1335 RelationGetRelationName(default_rel))));
>
> Relation name is already appended in error messgae.
> -----------------------------------------------------------------------------------------------------
> 4. src/backend/partitioning/partbounds.c
>
> 1363 if (!ExecCheck(partqualstate, econtext))
> 1364 ereport(ERROR,
> 1365 (errcode(ERRCODE_CHECK_VIOLATION),
> 1366 errmsg("updated partition constraint for default partition \"%s\" would be violated by some row",
> 1367 RelationGetRelationName(default_rel))));
>
> Relation name is already appended in error messgae.
> -----------------------------------------------------------------------------------------------------
> 5. src/backend/executor/execPartition.c
>
> 342 ereport(ERROR,
> 343 (errcode(ERRCODE_CHECK_VIOLATION),
> 344 errmsg("no partition of relation \"%s\" found for row",
> 345 RelationGetRelationName(rel)),
> 346 val_desc ?
> 347 errdetail("Partition key of the failing row contains %s.",
> 348 val_desc) : 0));
>
> Relation name is already appended in error messgae.
> -----------------------------------------------------------------------------------------------------
> 6. src/backend/executor/execMain.c
>
> 1877 ereport(ERROR,
> 1878 (errcode(ERRCODE_CHECK_VIOLATION),
> 1879 errmsg("new row for relation \"%s\" violates partition constraint",
> 1880 RelationGetRelationName(resultRelInfo->ri_RelationDesc)),
> 1881 val_desc ? errdetail("Failing row contains %s.", val_desc) : 0));
>
> Relation name is already appended in error messgae.
> -----------------------------------------------------------------------------------------------------
> 7. src/backend/executor/execMain.c
>
> 1958 ereport(ERROR,
> 1959 (errcode(ERRCODE_NOT_NULL_VIOLATION),
> 1960 errmsg("null value in column \"%s\" violates not-null constraint",
> 1961 NameStr(att->attname)),
> 1962 val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
> 1963 errtablecol(orig_rel, attrChk)));
>
> Added relation name for this error. This can be verified by below example:
> Ex:
> CREATE TABLE test (a int PRIMARY KEY, b int GENERATED ALWAYS AS (nullif(a, 0)) STORED NOT NULL);
> INSERT INTO test (a) VALUES (1);
> INSERT INTO test (a) VALUES (0);
>
> Without patch:
> ERROR: null value in column "b" violates not-null constraint
> DETAIL: Failing row contains (0, null).
> With patch:
> ERROR: null value in column "b" of relation "test" violates not-null constraint
> DETAIL: Failing row contains (0, null).
> -----------------------------------------------------------------------------------------------------
> 8. src/backend/executor/execMain.c
>
> 2006 ereport(ERROR,
> 2007 (errcode(ERRCODE_CHECK_VIOLATION),
> 2008 errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
> 2009 RelationGetRelationName(orig_rel), failed),
> 2010 val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
> 2011 errtableconstraint(orig_rel, failed)));
>
> Relation name is already appended in error messgae.
> -----------------------------------------------------------------------------------------------------
> 9. src/backend/executor/execExprInterp.c
>
> 3600 ereport(ERROR,
> 3601 (errcode(ERRCODE_NOT_NULL_VIOLATION),
> 3602 errmsg("domain %s does not allow null values",
> 3603 format_type_be(op->d.domaincheck.resulttype)),
> 3604 errdatatype(op->d.domaincheck.resulttype)));
>
> I think, above error is for domain, so there is no need to add anything in error message.
> -----------------------------------------------------------------------------------------------------
> 10. src/backend/executor/execExprInterp.c
>
> 3615 ereport(ERROR,
> 3616 (errcode(ERRCODE_CHECK_VIOLATION),
> 3617 errmsg("value for domain %s violates check constraint \"%s\"",
> 3618 format_type_be(op->d.domaincheck.resulttype),
> 3619 op->d.domaincheck.constraintname),
> 3620 errdomainconstraint(op->d.domaincheck.resulttype,
> 3621 op->d.domaincheck.constraintname)));
>
> I think, above error is for domain, so there is no need to add anything in error message.
> -----------------------------------------------------------------------------------------------------
> 11. src/backend/commands/tablecmds.c
>
> 5273 ereport(ERROR,
> 5274 (errcode(ERRCODE_NOT_NULL_VIOLATION),
> 5275 errmsg("column \"%s\" contains null values",
> 5276 NameStr(attr->attname)),
> 5277 errtablecol(oldrel, attn + 1)));
>
> Added relation name for this error. This can be verified by below example:
> Ex:
> CREATE TABLE test (a int);
> INSERT INTO test VALUES (0), (1);
> ALTER TABLE test ADD COLUMN b int NOT NULL, ALTER COLUMN b ADD GENERATED ALWAYS AS IDENTITY;
>
> Without patch:
> ERROR: column "b" contains null values
> With patch:
> ERROR: column "b" of relation "test" contains null values
> -----------------------------------------------------------------------------------------------------
> 12. src/backend/commands/tablecmds.c
>
> 5288 if (!ExecCheck(con->qualstate, econtext))
> 5289 ereport(ERROR,
> 5290 (errcode(ERRCODE_CHECK_VIOLATION),
> 5291 errmsg("check constraint \"%s\" is violated by some row",
> 5292 con->name),
> 5293 errtableconstraint(oldrel, con->name)));
>
> Added relation name for this error. This can be verified by below example:
> Ex:
> CREATE TABLE test (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STORED);
> INSERT INTO test (a) VALUES (10), (30);
> ALTER TABLE test ADD CHECK (b < 50);
>
> Without patch:
> ERROR: check constraint "test_b_check" is violated by some row
> With patch:
> ERROR: check constraint "test_b_check" of relation "test" is violated by some row
> -----------------------------------------------------------------------------------------------------
> 13. src/backend/commands/tablecmds.c
>
> 5306 if (tab->validate_default)
> 5307 ereport(ERROR,
> 5308 (errcode(ERRCODE_CHECK_VIOLATION),
> 5309 errmsg("updated partition constraint for default partition would be violated by some row")));
>
> Added relation name for this error. This can be verified by below example:
> Ex:
> CREATE TABLE list_parted ( a int, b char ) PARTITION BY LIST (a);
> CREATE TABLE list_parted_def PARTITION OF list_parted DEFAULT;
> INSERT INTO list_parted_def VALUES (11, 'z');
> CREATE TABLE part_1 (LIKE list_parted);
> ALTER TABLE list_parted ATTACH PARTITION part_1 FOR VALUES IN (11);
>
> Without patch:
> ERROR: updated partition constraint for default partition would be violated by some row
> With patch:
> ERROR: updated partition constraint for default partition "list_parted_def" would be violated by some row
> -----------------------------------------------------------------------------------------------------
> 14. src/backend/commands/tablecmds.c
>
> 5310 else
> 5311 ereport(ERROR,
> 5312 (errcode(ERRCODE_CHECK_VIOLATION),
> 5313 errmsg("partition constraint is violated by some row")));
>
> Added relation name for this error. This can be verified by below example:
> Ex:
> CREATE TABLE list_parted (a int,b char)PARTITION BY LIST (a);
> CREATE TABLE part_1 (LIKE list_parted);
> INSERT INTO part_1 VALUES (3, 'a');
> ALTER TABLE list_parted ATTACH PARTITION part_1 FOR VALUES IN (2);
>
> Without patch:
> ERROR: partition constraint is violated by some row
> With patch:
> ERROR: partition constraint "part_1" is violated by some row
Here it seems as if "part_1" is the constraint name. It would be
better to change it to:
partition constraint is violated by some row in relation "part_1" OR
partition constraint of relation "part_1" is violated b some row
> ---------------------------------------------------------------------------
> 15. src/backend/commands/tablecmds.c
>
> 10141 ereport(ERROR,
> 10142 (errcode(ERRCODE_CHECK_VIOLATION),
> 10143 errmsg("check constraint \"%s\" is violated by some row",
> 10144 NameStr(constrForm->conname)),
> 10145 errtableconstraint(rel, NameStr(constrForm->conname))));
>
> Added relation name for this error. This can be verified by below example:
> Ex:
> CREATE TABLE test (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STORED);
> INSERT INTO test (a) VALUES (10), (30);
> ALTER TABLE test ADD CONSTRAINT chk CHECK (b < 50) NOT VALID;
> ALTER TABLE test VALIDATE CONSTRAINT chk;
>
> Without patch:
> ERROR: check constraint "chk" is violated by some row
> With patch:
> ERROR: check constraint "chk" of relation "test" is violated by some row
> -----------------------------------------------------------------------------------------------------
> 16. src/backend/commands/typecmds.c
>
> 2396 ereport(ERROR,
> 2397 (errcode(ERRCODE_NOT_NULL_VIOLATION),
> 2398 errmsg("column \"%s\" of table \"%s\" contains null values",
> 2399 NameStr(attr->attname),
> 2400 RelationGetRelationName(testrel)),
> 2401 errtablecol(testrel, attnum)));
>
> Relation name is already appended in error messgae.
> -----------------------------------------------------------------------------------------------------
> 17. src/backend/commands/typecmds.c
>
> 2824 ereport(ERROR,
> 2825 (errcode(ERRCODE_CHECK_VIOLATION),
> 2826 errmsg("column \"%s\" of table \"%s\" contains values that violate the new constraint",
> 2827 NameStr(attr->attname),
> 2828 RelationGetRelationName(testrel)),
> 2829 errtablecol(testrel, attnum)));
>
> Relation name is already appended in error messgae.
> -----------------------------------------------------------------------------------------------------
> 18. src/backend/commands/typecmds.c
>
> 2396 ereport(ERROR,
> 2397 (errcode(ERRCODE_NOT_NULL_VIOLATION),
> 2398 errmsg("column \"%s\" of table \"%s\" contains null values",
> 2399 NameStr(attr->attname),
> 2400 RelationGetRelationName(testrel)),
> 2401 errtablecol(testrel, attnum)));
>
> Relation name is already appended in error messgae.
> -----------------------------------------------------------------------------------------------------
> 19. src/backend/commands/typecmds.c
>
> 2824 ereport(ERROR,
> 2825 (errcode(ERRCODE_CHECK_VIOLATION),
> 2826 errmsg("column \"%s\" of table \"%s\" contains values that violate the new constraint",
> 2827 NameStr(attr->attname),
> 2828 RelationGetRelationName(testrel)),
> 2829 errtablecol(testrel, attnum)))
>
> Relation name is already appended in error messgae.
> -----------------------------------------------------------------------------------------------------
> >
> > > What does this patch?
> > > Before this patch, to display error of "not-null constraint", we were not displaying relation name in some cases so attached patch is adding relation name with the "not-null constraint" error in 2 places. I didn't changed out files of test suite as we haven't finalized error messages.
> > >
> > > I verified Robert's point of for partition tables also. With the error, we are adding relation name of "child table" and i think, it is correct.
> > >
> >
> > Can you show the same with the help of an example?
>
> Okay. Below is the example:
> create table parent (a int, b int not null) partition by range (a);
> create table ch1 partition of parent for values from ( 10 ) to (20);
> postgres=# insert into parent values (9);
> ERROR: no partition of relation "parent" found for row
> DETAIL: Partition key of the failing row contains (a) = (9).
> postgres=# insert into parent values (11);
> ERROR: null value in column "b" of relation "ch1" violates not-null constraint
> DETAIL: Failing row contains (11, null).
>
> Attaching a patch for review. In this patch, total 6 places I added relation name in error message and verifyed same with above mentioned examples.
>
> Please review attahced patch and let me know your feedback. I haven't modifed .out files because we haven't finalied patch.
>
--
M Beena Emerson
EnterpriseDB: http://www.enterprisedb.com
^ permalink raw reply [nested|flat] 1934+ messages in thread
* Re: Error message inconsistency
@ 2020-01-22 13:32 Alvaro Herrera <[email protected]>
parent: MBeena Emerson <[email protected]>
1 sibling, 1 reply; 1934+ messages in thread
From: Alvaro Herrera @ 2020-01-22 13:32 UTC (permalink / raw)
To: MBeena Emerson <[email protected]>; +Cc: Mahendra Singh Thalor <[email protected]>; Amit Kapila <[email protected]>; Simon Riggs <[email protected]>; Fabrízio Mello <[email protected]>; PostgreSQL Hackers <[email protected]>
I wonder if we shouldn't be using errtablecol() here instead of (in
addition to?) patching the errmsg() to include the table name.
Discussion: If we really like having the table names in errtable(), then
we should have psql display it by default, and other tools will follow
suit; in that case we should remove the table name from error messages,
or at least not add it to even more messages.
If we instead think that errtable() is there just for programmatically
knowing the affected table, then we should add the table name to all
errmsg() where relevant, as in the patch under discussion.
What do others think?
--
Álvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
^ permalink raw reply [nested|flat] 1934+ messages in thread
* Re: Error message inconsistency
@ 2020-01-22 15:18 Tom Lane <[email protected]>
parent: Alvaro Herrera <[email protected]>
0 siblings, 1 reply; 1934+ messages in thread
From: Tom Lane @ 2020-01-22 15:18 UTC (permalink / raw)
To: Alvaro Herrera <[email protected]>; +Cc: MBeena Emerson <[email protected]>; Mahendra Singh Thalor <[email protected]>; Amit Kapila <[email protected]>; Simon Riggs <[email protected]>; Fabrízio Mello <[email protected]>; PostgreSQL Hackers <[email protected]>
Alvaro Herrera <[email protected]> writes:
> I wonder if we shouldn't be using errtablecol() here instead of (in
> addition to?) patching the errmsg() to include the table name.
> Discussion: If we really like having the table names in errtable(), then
> we should have psql display it by default, and other tools will follow
> suit; in that case we should remove the table name from error messages,
> or at least not add it to even more messages.
> If we instead think that errtable() is there just for programmatically
> knowing the affected table, then we should add the table name to all
> errmsg() where relevant, as in the patch under discussion.
> What do others think?
I believe that the intended use of errtable() and friends is so that
applications don't have to parse those names out of a human-friendly
message. We should add calls to them in cases where (a) an application
can tell from the SQLSTATE that some particular table is involved
and (b) it's likely that the app would wish to know which table that is.
I don't feel a need to sprinkle every single ereport() in the backend
with errtable(), just ones where there's a plausible use-case for the
extra cycles that will be spent.
On the other side of the coin, whether we use errtable() is not directly
a factor in deciding what the human-friendly messages should say.
I do find it hard to envision a case where we'd want to use errtable()
and *not* put the table name in the error message, just because if
applications need to know something then humans probably do too. But
saying that we can make the messages omit info because it's available
from these program-friendly fields seems 100% wrong to me, even if one
turns a blind eye to the fact that existing client code likely won't
show those fields to users.
regards, tom lane
^ permalink raw reply [nested|flat] 1934+ messages in thread
* Re: Error message inconsistency
@ 2020-01-23 04:31 Amit Kapila <[email protected]>
parent: MBeena Emerson <[email protected]>
1 sibling, 0 replies; 1934+ messages in thread
From: Amit Kapila @ 2020-01-23 04:31 UTC (permalink / raw)
To: MBeena Emerson <[email protected]>; +Cc: Mahendra Singh Thalor <[email protected]>; Alvaro Herrera <[email protected]>; Simon Riggs <[email protected]>; Fabrízio Mello <[email protected]>; PostgreSQL Hackers <[email protected]>
On Wed, Jan 22, 2020 at 3:23 PM MBeena Emerson <[email protected]> wrote:
>
> > -----------------------------------------------------------------------------------------------------
> > 14. src/backend/commands/tablecmds.c
> >
> > 5310 else
> > 5311 ereport(ERROR,
> > 5312 (errcode(ERRCODE_CHECK_VIOLATION),
> > 5313 errmsg("partition constraint is violated by some row")));
> >
> > Added relation name for this error. This can be verified by below example:
> > Ex:
> > CREATE TABLE list_parted (a int,b char)PARTITION BY LIST (a);
> > CREATE TABLE part_1 (LIKE list_parted);
> > INSERT INTO part_1 VALUES (3, 'a');
> > ALTER TABLE list_parted ATTACH PARTITION part_1 FOR VALUES IN (2);
> >
> > Without patch:
> > ERROR: partition constraint is violated by some row
> > With patch:
> > ERROR: partition constraint "part_1" is violated by some row
>
> Here it seems as if "part_1" is the constraint name.
>
I agree.
> It would be
> better to change it to:
>
> partition constraint is violated by some row in relation "part_1" OR
> partition constraint of relation "part_1" is violated b some row
>
+1 for the second option suggested by Beena.
--
With Regards,
Amit Kapila.
EnterpriseDB: http://www.enterprisedb.com
^ permalink raw reply [nested|flat] 1934+ messages in thread
* Re: Error message inconsistency
@ 2020-01-23 04:50 Amit Kapila <[email protected]>
parent: Tom Lane <[email protected]>
0 siblings, 1 reply; 1934+ messages in thread
From: Amit Kapila @ 2020-01-23 04:50 UTC (permalink / raw)
To: Tom Lane <[email protected]>; +Cc: Alvaro Herrera <[email protected]>; MBeena Emerson <[email protected]>; Mahendra Singh Thalor <[email protected]>; Simon Riggs <[email protected]>; Fabrízio Mello <[email protected]>; PostgreSQL Hackers <[email protected]>
On Wed, Jan 22, 2020 at 8:48 PM Tom Lane <[email protected]> wrote:
>
> Alvaro Herrera <[email protected]> writes:
> > I wonder if we shouldn't be using errtablecol() here instead of (in
> > addition to?) patching the errmsg() to include the table name.
>
> > Discussion: If we really like having the table names in errtable(), then
> > we should have psql display it by default, and other tools will follow
> > suit; in that case we should remove the table name from error messages,
> > or at least not add it to even more messages.
>
> > If we instead think that errtable() is there just for programmatically
> > knowing the affected table, then we should add the table name to all
> > errmsg() where relevant, as in the patch under discussion.
>
> > What do others think?
>
> I believe that the intended use of errtable() and friends is so that
> applications don't have to parse those names out of a human-friendly
> message. We should add calls to them in cases where (a) an application
> can tell from the SQLSTATE that some particular table is involved
> and (b) it's likely that the app would wish to know which table that is.
> I don't feel a need to sprinkle every single ereport() in the backend
> with errtable(), just ones where there's a plausible use-case for the
> extra cycles that will be spent.
>
> On the other side of the coin, whether we use errtable() is not directly
> a factor in deciding what the human-friendly messages should say.
> I do find it hard to envision a case where we'd want to use errtable()
> and *not* put the table name in the error message, just because if
> applications need to know something then humans probably do too.
>
makes sense.
--
With Regards,
Amit Kapila.
EnterpriseDB: http://www.enterprisedb.com
^ permalink raw reply [nested|flat] 1934+ messages in thread
* Re: Error message inconsistency
@ 2020-01-23 12:21 Mahendra Singh Thalor <[email protected]>
parent: Amit Kapila <[email protected]>
0 siblings, 1 reply; 1934+ messages in thread
From: Mahendra Singh Thalor @ 2020-01-23 12:21 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Tom Lane <[email protected]>; Alvaro Herrera <[email protected]>; MBeena Emerson <[email protected]>; Simon Riggs <[email protected]>; Fabrízio Mello <[email protected]>; PostgreSQL Hackers <[email protected]>
On Thu, 23 Jan 2020 at 10:20, Amit Kapila <[email protected]> wrote:
>
> On Wed, Jan 22, 2020 at 8:48 PM Tom Lane <[email protected]> wrote:
> >
> > Alvaro Herrera <[email protected]> writes:
> > > I wonder if we shouldn't be using errtablecol() here instead of (in
> > > addition to?) patching the errmsg() to include the table name.
> >
> > > Discussion: If we really like having the table names in errtable(), then
> > > we should have psql display it by default, and other tools will follow
> > > suit; in that case we should remove the table name from error messages,
> > > or at least not add it to even more messages.
> >
> > > If we instead think that errtable() is there just for programmatically
> > > knowing the affected table, then we should add the table name to all
> > > errmsg() where relevant, as in the patch under discussion.
> >
> > > What do others think?
> >
> > I believe that the intended use of errtable() and friends is so that
> > applications don't have to parse those names out of a human-friendly
> > message. We should add calls to them in cases where (a) an application
> > can tell from the SQLSTATE that some particular table is involved
> > and (b) it's likely that the app would wish to know which table that is.
> > I don't feel a need to sprinkle every single ereport() in the backend
> > with errtable(), just ones where there's a plausible use-case for the
> > extra cycles that will be spent.
> >
> > On the other side of the coin, whether we use errtable() is not directly
> > a factor in deciding what the human-friendly messages should say.
> > I do find it hard to envision a case where we'd want to use errtable()
> > and *not* put the table name in the error message, just because if
> > applications need to know something then humans probably do too.
> >
>
> makes sense.
>
Thanks all for reviewing and giving comments.
> > > Added relation name for this error. This can be verified by below example:
> > > Ex:
> > > CREATE TABLE list_parted (a int,b char)PARTITION BY LIST (a);
> > > CREATE TABLE part_1 (LIKE list_parted);
> > > INSERT INTO part_1 VALUES (3, 'a');
> > > ALTER TABLE list_parted ATTACH PARTITION part_1 FOR VALUES IN (2);
> > >
> > > Without patch:
> > > ERROR: partition constraint is violated by some row
> > > With patch:
> > > ERROR: partition constraint "part_1" is violated by some row
> >
> > Here it seems as if "part_1" is the constraint name.
> >
>
> I agree.
>
> > It would be
> > better to change it to:
> >
> > partition constraint is violated by some row in relation "part_1" OR
> > partition constraint of relation "part_1" is violated b some row
> >
>
> +1 for the second option suggested by Beena.
I fixed above comment and updated expected .out files. Attaching
updated patches.
To make review simple, I made 3 patches as:
v4_0001_rationalize_constraint_error_messages.patch:
This patch has .c file changes. Added relation name in 6 error
messages for check constraint.
v4_0002_updated-regress-expected-.out-files.patch:
This patch has changes of expected .out files for regress test suite.
v4_0003_updated-constraints.source-file.patch:
This patch has changes of .source file for constraints.sql regress test.
Please review attached patches and let me know your comments.
--
Thanks and Regards
Mahendra Singh Thalor
EnterpriseDB: http://www.enterprisedb.com
Attachments:
[application/octet-stream] v4_0001_rationalize_constraint_error_messages.patch (3.6K, ../../CAKYtNAo9Nf0us=hzDKd7WbMxMvXx6mPcCOkhQXVOsH9U-8qw9A@mail.gmail.com/2-v4_0001_rationalize_constraint_error_messages.patch)
download | inline diff:
From 08c89ce460360b13b5cbe62836d67a10627cc14e Mon Sep 17 00:00:00 2001
From: Mahendra Singh Thalor <[email protected]>
Date: Thu, 23 Jan 2020 17:01:53 +0530
Subject: [PATCH 1/3] Added relation name in error messages for constraint
check
---
src/backend/commands/tablecmds.c | 21 +++++++++++++--------
src/backend/executor/execMain.c | 5 +++--
2 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 7c23968..70589dd 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -5288,8 +5288,9 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
ereport(ERROR,
(errcode(ERRCODE_NOT_NULL_VIOLATION),
- errmsg("column \"%s\" contains null values",
- NameStr(attr->attname)),
+ errmsg("column \"%s\" of relation \"%s\" contains null values",
+ NameStr(attr->attname),
+ RelationGetRelationName(oldrel)),
errtablecol(oldrel, attn + 1)));
}
}
@@ -5304,8 +5305,9 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
if (!ExecCheck(con->qualstate, econtext))
ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION),
- errmsg("check constraint \"%s\" is violated by some row",
- con->name),
+ errmsg("check constraint \"%s\" of relation \"%s\" is violated by some row",
+ con->name,
+ RelationGetRelationName(oldrel)),
errtableconstraint(oldrel, con->name)));
break;
case CONSTR_FOREIGN:
@@ -5322,11 +5324,13 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
if (tab->validate_default)
ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION),
- errmsg("updated partition constraint for default partition would be violated by some row")));
+ errmsg("updated partition constraint for default partition \"%s\" would be violated by some row",
+ RelationGetRelationName(oldrel))));
else
ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION),
- errmsg("partition constraint is violated by some row")));
+ errmsg("partition constraint of relation \"%s\" is violated by some row",
+ RelationGetRelationName(oldrel))));
}
/* Write the tuple out to the new relation */
@@ -10160,8 +10164,9 @@ validateCheckConstraint(Relation rel, HeapTuple constrtup)
if (!ExecCheck(exprstate, econtext))
ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION),
- errmsg("check constraint \"%s\" is violated by some row",
- NameStr(constrForm->conname)),
+ errmsg("check constraint \"%s\" of relation \"%s\" is violated by some row",
+ NameStr(constrForm->conname),
+ RelationGetRelationName(rel)),
errtableconstraint(rel, NameStr(constrForm->conname))));
ResetExprContext(econtext);
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index b03e02a..3a9ce99 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -1957,8 +1957,9 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
ereport(ERROR,
(errcode(ERRCODE_NOT_NULL_VIOLATION),
- errmsg("null value in column \"%s\" violates not-null constraint",
- NameStr(att->attname)),
+ errmsg("null value in column \"%s\" of relation \"%s\" violates not-null constraint",
+ NameStr(att->attname),
+ RelationGetRelationName(orig_rel)),
val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
errtablecol(orig_rel, attrChk)));
}
--
1.8.3.1
[application/octet-stream] v4_0002_updated-regress-expected-.out-files.patch (32.2K, ../../CAKYtNAo9Nf0us=hzDKd7WbMxMvXx6mPcCOkhQXVOsH9U-8qw9A@mail.gmail.com/3-v4_0002_updated-regress-expected-.out-files.patch)
download | inline diff:
From 0f556d3200b58ddf4165b30a1317ce50cc77ee13 Mon Sep 17 00:00:00 2001
From: Mahendra Singh Thalor <[email protected]>
Date: Thu, 23 Jan 2020 17:02:49 +0530
Subject: [PATCH 2/3] updated regress/expected .out files
---
src/test/regress/expected/alter_table.out | 76 ++++++++++++-------------
src/test/regress/expected/copy2.out | 2 +-
src/test/regress/expected/create_table.out | 2 +-
src/test/regress/expected/create_table_like.out | 2 +-
src/test/regress/expected/domain.out | 8 +--
src/test/regress/expected/generated.out | 8 +--
src/test/regress/expected/identity.out | 4 +-
src/test/regress/expected/index_including.out | 4 +-
src/test/regress/expected/inherit.out | 6 +-
src/test/regress/expected/insert.out | 2 +-
src/test/regress/expected/privileges.out | 6 +-
src/test/regress/expected/reloptions.out | 4 +-
src/test/regress/expected/sequence.out | 2 +-
src/test/regress/expected/vacuum.out | 2 +-
14 files changed, 64 insertions(+), 64 deletions(-)
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index 4dd3507..e73ce4b 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -457,10 +457,10 @@ ALTER TABLE attmp3 validate constraint attmpconstr;
ALTER TABLE attmp3 validate constraint attmpconstr;
-- Try a non-verified CHECK constraint
ALTER TABLE attmp3 ADD CONSTRAINT b_greater_than_ten CHECK (b > 10); -- fail
-ERROR: check constraint "b_greater_than_ten" is violated by some row
+ERROR: check constraint "b_greater_than_ten" of relation "attmp3" is violated by some row
ALTER TABLE attmp3 ADD CONSTRAINT b_greater_than_ten CHECK (b > 10) NOT VALID; -- succeeds
ALTER TABLE attmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- fails
-ERROR: check constraint "b_greater_than_ten" is violated by some row
+ERROR: check constraint "b_greater_than_ten" of relation "attmp3" is violated by some row
DELETE FROM attmp3 WHERE NOT b > 10;
ALTER TABLE attmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- succeeds
ALTER TABLE attmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- succeeds
@@ -476,7 +476,7 @@ CREATE TABLE attmp7 () INHERITS (attmp3);
INSERT INTO attmp6 VALUES (6, 30), (7, 16);
ALTER TABLE attmp3 ADD CONSTRAINT b_le_20 CHECK (b <= 20) NOT VALID;
ALTER TABLE attmp3 VALIDATE CONSTRAINT b_le_20; -- fails
-ERROR: check constraint "b_le_20" is violated by some row
+ERROR: check constraint "b_le_20" of relation "attmp6" is violated by some row
DELETE FROM attmp6 WHERE b > 20;
ALTER TABLE attmp3 VALIDATE CONSTRAINT b_le_20; -- succeeds
-- An already validated constraint must not be revalidated
@@ -497,7 +497,7 @@ insert into child_noinh_convalid values (1);
alter table parent_noinh_convalid add constraint check_a_is_2 check (a = 2) no inherit not valid;
-- fail, because of the row in parent
alter table parent_noinh_convalid validate constraint check_a_is_2;
-ERROR: check constraint "check_a_is_2" is violated by some row
+ERROR: check constraint "check_a_is_2" of relation "parent_noinh_convalid" is violated by some row
delete from only parent_noinh_convalid;
-- ok (parent itself contains no violating rows)
alter table parent_noinh_convalid validate constraint check_a_is_2;
@@ -754,7 +754,7 @@ create table atacc1 ( test int );
insert into atacc1 (test) values (2);
-- add a check constraint (fails)
alter table atacc1 add constraint atacc_test1 check (test>3);
-ERROR: check constraint "atacc_test1" is violated by some row
+ERROR: check constraint "atacc_test1" of relation "atacc1" is violated by some row
insert into atacc1 (test) values (4);
drop table atacc1;
-- let's do one where the check fails because the column doesn't exist
@@ -867,7 +867,7 @@ DETAIL: Failing row contains (-3).
insert into atacc1 (test) values (3);
-- fail, violating row:
alter table atacc2 add constraint foo check (test>0) no inherit;
-ERROR: check constraint "foo" is violated by some row
+ERROR: check constraint "foo" of relation "atacc2" is violated by some row
drop table atacc2;
drop table atacc1;
-- test unique constraint adding
@@ -943,7 +943,7 @@ DETAIL: Key (test)=(2) already exists.
insert into atacc1 (test) values (4);
-- inserting NULL should fail
insert into atacc1 (test) values(NULL);
-ERROR: null value in column "test" violates not-null constraint
+ERROR: null value in column "test" of relation "atacc1" violates not-null constraint
DETAIL: Failing row contains (4, null).
-- try adding a second primary key (should fail)
alter table atacc1 add constraint atacc_oid1 primary key(id);
@@ -970,7 +970,7 @@ create table atacc1 ( test int );
insert into atacc1 (test) values (NULL);
-- add a primary key (fails)
alter table atacc1 add constraint atacc_test1 primary key (test);
-ERROR: column "test" contains null values
+ERROR: column "test" of relation "atacc1" contains null values
insert into atacc1 (test) values (3);
drop table atacc1;
-- let's do one where the primary key constraint fails
@@ -986,7 +986,7 @@ create table atacc1 ( test int );
insert into atacc1 (test) values (0);
-- add a primary key column without a default (fails).
alter table atacc1 add column test2 int primary key;
-ERROR: column "test2" contains null values
+ERROR: column "test2" of relation "atacc1" contains null values
-- now add a primary key column with a default (succeeds).
alter table atacc1 add column test2 int default 0 primary key;
drop table atacc1;
@@ -1011,13 +1011,13 @@ insert into atacc1 (test,test2) values (4,4);
ERROR: duplicate key value violates unique constraint "atacc_test1"
DETAIL: Key (test, test2)=(4, 4) already exists.
insert into atacc1 (test,test2) values (NULL,3);
-ERROR: null value in column "test" violates not-null constraint
+ERROR: null value in column "test" of relation "atacc1" violates not-null constraint
DETAIL: Failing row contains (null, 3).
insert into atacc1 (test,test2) values (3, NULL);
-ERROR: null value in column "test2" violates not-null constraint
+ERROR: null value in column "test2" of relation "atacc1" violates not-null constraint
DETAIL: Failing row contains (3, null).
insert into atacc1 (test,test2) values (NULL,NULL);
-ERROR: null value in column "test" violates not-null constraint
+ERROR: null value in column "test" of relation "atacc1" violates not-null constraint
DETAIL: Failing row contains (null, null).
-- should all succeed
insert into atacc1 (test,test2) values (4,5);
@@ -1032,7 +1032,7 @@ insert into atacc1 (test2, test) values (2, 3);
ERROR: duplicate key value violates unique constraint "atacc1_pkey"
DETAIL: Key (test)=(3) already exists.
insert into atacc1 (test2, test) values (1, NULL);
-ERROR: null value in column "test" violates not-null constraint
+ERROR: null value in column "test" of relation "atacc1" violates not-null constraint
DETAIL: Failing row contains (null, 1).
drop table atacc1;
-- alter table / alter column [set/drop] not null tests
@@ -1056,7 +1056,7 @@ alter table atacc1 drop constraint "atacc1_pkey";
alter table atacc1 alter column test drop not null;
insert into atacc1 values (null);
alter table atacc1 alter test set not null;
-ERROR: column "test" contains null values
+ERROR: column "test" of relation "atacc1" contains null values
delete from atacc1;
alter table atacc1 alter test set not null;
-- try altering a non-existent column, should fail
@@ -1078,12 +1078,12 @@ insert into atacc1 values (null, 1);
-- constraint not cover all values, should fail
alter table atacc1 add constraint atacc1_constr_or check(test_a is not null or test_b < 10);
alter table atacc1 alter test_a set not null;
-ERROR: column "test_a" contains null values
+ERROR: column "test_a" of relation "atacc1" contains null values
alter table atacc1 drop constraint atacc1_constr_or;
-- not valid constraint, should fail
alter table atacc1 add constraint atacc1_constr_invalid check(test_a is not null) not valid;
alter table atacc1 alter test_a set not null;
-ERROR: column "test_a" contains null values
+ERROR: column "test_a" of relation "atacc1" contains null values
alter table atacc1 drop constraint atacc1_constr_invalid;
-- with valid constraint
update atacc1 set test_a = 1;
@@ -1095,10 +1095,10 @@ alter table atacc1 alter test_a drop not null;
-- test multiple set not null at same time
-- test_a checked by atacc1_constr_a_valid, test_b should fail by table scan
alter table atacc1 alter test_a set not null, alter test_b set not null;
-ERROR: column "test_b" contains null values
+ERROR: column "test_b" of relation "atacc1" contains null values
-- commands order has no importance
alter table atacc1 alter test_b set not null, alter test_a set not null;
-ERROR: column "test_b" contains null values
+ERROR: column "test_b" of relation "atacc1" contains null values
-- valid one by table scan, one by check constraints
update atacc1 set test_b = 1;
alter table atacc1 alter test_b set not null, alter test_a set not null;
@@ -1112,31 +1112,31 @@ create table parent (a int);
create table child (b varchar(255)) inherits (parent);
alter table parent alter a set not null;
insert into parent values (NULL);
-ERROR: null value in column "a" violates not-null constraint
+ERROR: null value in column "a" of relation "parent" violates not-null constraint
DETAIL: Failing row contains (null).
insert into child (a, b) values (NULL, 'foo');
-ERROR: null value in column "a" violates not-null constraint
+ERROR: null value in column "a" of relation "child" violates not-null constraint
DETAIL: Failing row contains (null, foo).
alter table parent alter a drop not null;
insert into parent values (NULL);
insert into child (a, b) values (NULL, 'foo');
alter table only parent alter a set not null;
-ERROR: column "a" contains null values
+ERROR: column "a" of relation "parent" contains null values
alter table child alter a set not null;
-ERROR: column "a" contains null values
+ERROR: column "a" of relation "child" contains null values
delete from parent;
alter table only parent alter a set not null;
insert into parent values (NULL);
-ERROR: null value in column "a" violates not-null constraint
+ERROR: null value in column "a" of relation "parent" violates not-null constraint
DETAIL: Failing row contains (null).
alter table child alter a set not null;
insert into child (a, b) values (NULL, 'foo');
-ERROR: null value in column "a" violates not-null constraint
+ERROR: null value in column "a" of relation "child" violates not-null constraint
DETAIL: Failing row contains (null, foo).
delete from child;
alter table child alter a set not null;
insert into child (a, b) values (NULL, 'foo');
-ERROR: null value in column "a" violates not-null constraint
+ERROR: null value in column "a" of relation "child" violates not-null constraint
DETAIL: Failing row contains (null, foo).
drop table child;
drop table parent;
@@ -1474,7 +1474,7 @@ insert into atacc1(value) values (100);
ERROR: new row for relation "atacc1" violates check constraint "atacc1_value_check"
DETAIL: Failing row contains (2, 100).
insert into atacc1(id, value) values (null, 0);
-ERROR: null value in column "id" violates not-null constraint
+ERROR: null value in column "id" of relation "atacc1" violates not-null constraint
DETAIL: Failing row contains (null, 0).
drop table atacc1;
-- test inheritance
@@ -3804,7 +3804,7 @@ CREATE TABLE list_parted2 (
CREATE TABLE part_2 (LIKE list_parted2);
INSERT INTO part_2 VALUES (3, 'a');
ALTER TABLE list_parted2 ATTACH PARTITION part_2 FOR VALUES IN (2);
-ERROR: partition constraint is violated by some row
+ERROR: partition constraint of relation "part_2" is violated by some row
-- should be ok after deleting the bad row
DELETE FROM part_2;
ALTER TABLE list_parted2 ATTACH PARTITION part_2 FOR VALUES IN (2);
@@ -3813,7 +3813,7 @@ CREATE TABLE list_parted2_def PARTITION OF list_parted2 DEFAULT;
INSERT INTO list_parted2_def VALUES (11, 'z');
CREATE TABLE part_3 (LIKE list_parted2);
ALTER TABLE list_parted2 ATTACH PARTITION part_3 FOR VALUES IN (11);
-ERROR: updated partition constraint for default partition would be violated by some row
+ERROR: updated partition constraint for default partition "list_parted2_def" would be violated by some row
-- should be ok after deleting the bad row
DELETE FROM list_parted2_def WHERE a = 11;
ALTER TABLE list_parted2 ATTACH PARTITION part_3 FOR VALUES IN (11);
@@ -3847,7 +3847,7 @@ CREATE TABLE part1 (
INSERT INTO part1 VALUES (1, 10);
-- Remember the TO bound is exclusive
ALTER TABLE range_parted ATTACH PARTITION part1 FOR VALUES FROM (1, 1) TO (1, 10);
-ERROR: partition constraint is violated by some row
+ERROR: partition constraint of relation "part1" is violated by some row
-- should be ok after deleting the bad row
DELETE FROM part1;
ALTER TABLE range_parted ATTACH PARTITION part1 FOR VALUES FROM (1, 1) TO (1, 10);
@@ -3868,7 +3868,7 @@ ERROR: partition "partr_def2" conflicts with existing default partition "partr_
INSERT INTO partr_def1 VALUES (2, 10);
CREATE TABLE part3 (LIKE range_parted);
ALTER TABLE range_parted ATTACH partition part3 FOR VALUES FROM (2, 10) TO (2, 20);
-ERROR: updated partition constraint for default partition would be violated by some row
+ERROR: updated partition constraint for default partition "partr_def1" would be violated by some row
-- Attaching partitions should be successful when there are no overlapping rows
ALTER TABLE range_parted ATTACH partition part3 FOR VALUES FROM (3, 10) TO (3, 20);
-- check that leaf partitions are scanned when attaching a partitioned
@@ -3880,7 +3880,7 @@ CREATE TABLE part_5 (
CREATE TABLE part_5_a PARTITION OF part_5 FOR VALUES IN ('a');
INSERT INTO part_5_a (a, b) VALUES (6, 'a');
ALTER TABLE list_parted2 ATTACH PARTITION part_5 FOR VALUES IN (5);
-ERROR: partition constraint is violated by some row
+ERROR: partition constraint of relation "part_5_a" is violated by some row
-- delete the faulting row and also add a constraint to skip the scan
DELETE FROM part_5_a WHERE a NOT IN (3);
ALTER TABLE part_5 ADD CONSTRAINT check_a CHECK (a IS NOT NULL AND a = 5);
@@ -3931,7 +3931,7 @@ SELECT tableoid::regclass, a, b FROM part_7 order by a;
(2 rows)
ALTER TABLE list_parted2 ATTACH PARTITION part_7 FOR VALUES IN (7);
-ERROR: partition constraint is violated by some row
+ERROR: partition constraint of relation "part_7_a_null" is violated by some row
-- check that leaf partitions of default partition are scanned when
-- attaching a partitioned table.
ALTER TABLE part_5 DROP CONSTRAINT check_a;
@@ -3940,7 +3940,7 @@ CREATE TABLE part5_def_p1 PARTITION OF part5_def FOR VALUES IN (5);
INSERT INTO part5_def_p1 VALUES (5, 'y');
CREATE TABLE part5_p1 (LIKE part_5);
ALTER TABLE part_5 ATTACH PARTITION part5_p1 FOR VALUES IN ('y');
-ERROR: updated partition constraint for default partition would be violated by some row
+ERROR: updated partition constraint for default partition "part5_def_p1" would be violated by some row
-- should be ok after deleting the bad row
DELETE FROM part5_def_p1 WHERE b = 'y';
ALTER TABLE part_5 ATTACH PARTITION part5_p1 FOR VALUES IN ('y');
@@ -3992,7 +3992,7 @@ DROP TABLE fail_part;
CREATE TABLE hpart_2 (LIKE hash_parted);
INSERT INTO hpart_2 VALUES (3, 0);
ALTER TABLE hash_parted ATTACH PARTITION hpart_2 FOR VALUES WITH (MODULUS 4, REMAINDER 1);
-ERROR: partition constraint is violated by some row
+ERROR: partition constraint of relation "hpart_2" is violated by some row
-- should be ok after deleting the bad row
DELETE FROM hpart_2;
ALTER TABLE hash_parted ATTACH PARTITION hpart_2 FOR VALUES WITH (MODULUS 4, REMAINDER 1);
@@ -4005,7 +4005,7 @@ CREATE TABLE hpart_5 (
CREATE TABLE hpart_5_a PARTITION OF hpart_5 FOR VALUES IN ('1', '2', '3');
INSERT INTO hpart_5_a (a, b) VALUES (7, 1);
ALTER TABLE hash_parted ATTACH PARTITION hpart_5 FOR VALUES WITH (MODULUS 4, REMAINDER 2);
-ERROR: partition constraint is violated by some row
+ERROR: partition constraint of relation "hpart_5_a" is violated by some row
-- should be ok after deleting the bad row
DELETE FROM hpart_5_a;
ALTER TABLE hash_parted ATTACH PARTITION hpart_5 FOR VALUES WITH (MODULUS 4, REMAINDER 2);
@@ -4172,7 +4172,7 @@ alter table p1 attach partition p11 for values from (2) to (5);
insert into p1 (a, b) values (2, 3);
-- check that partition validation scan correctly detects violating rows
alter table p attach partition p1 for values from (1, 2) to (1, 10);
-ERROR: partition constraint is violated by some row
+ERROR: partition constraint of relation "p11" is violated by some row
-- cleanup
drop table p;
drop table p1;
@@ -4200,7 +4200,7 @@ insert into defpart_attach_test_d values (1), (2);
-- error because its constraint as the default partition would be violated
-- by the row containing 1
alter table defpart_attach_test attach partition defpart_attach_test_d default;
-ERROR: partition constraint is violated by some row
+ERROR: partition constraint of relation "defpart_attach_test_d" is violated by some row
delete from defpart_attach_test_d where a = 1;
alter table defpart_attach_test_d add check (a > 1);
-- should be attached successfully and without needing to be scanned
@@ -4210,7 +4210,7 @@ alter table defpart_attach_test attach partition defpart_attach_test_d default;
-- successfully
create table defpart_attach_test_2 (like defpart_attach_test_d);
alter table defpart_attach_test attach partition defpart_attach_test_2 for values in (2);
-ERROR: updated partition constraint for default partition would be violated by some row
+ERROR: updated partition constraint for default partition "defpart_attach_test_d" would be violated by some row
drop table defpart_attach_test;
-- check combinations of temporary and permanent relations when attaching
-- partitions.
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index c53ed3e..e40287d 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -440,7 +440,7 @@ SELECT c, d FROM forcetest WHERE a = 2;
-- should fail with not-null constraint violation
BEGIN;
COPY forcetest (a, b, c) FROM STDIN WITH (FORMAT csv, FORCE_NULL(b), FORCE_NOT_NULL(c));
-ERROR: null value in column "b" violates not-null constraint
+ERROR: null value in column "b" of relation "forcetest" violates not-null constraint
DETAIL: Failing row contains (3, null, , null, null).
CONTEXT: COPY forcetest, line 1: "3,,"""
ROLLBACK;
diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out
index b64f919..c5e95ed 100644
--- a/src/test/regress/expected/create_table.out
+++ b/src/test/regress/expected/create_table.out
@@ -955,7 +955,7 @@ CREATE TABLE part_c_1_10 PARTITION OF part_c FOR VALUES FROM (1) TO (10);
create table parted_notnull_inh_test (a int default 1, b int not null default 0) partition by list (a);
create table parted_notnull_inh_test1 partition of parted_notnull_inh_test (a not null, b default 1) for values in (1);
insert into parted_notnull_inh_test (b) values (null);
-ERROR: null value in column "b" violates not-null constraint
+ERROR: null value in column "b" of relation "parted_notnull_inh_test1" violates not-null constraint
DETAIL: Failing row contains (1, null).
-- note that while b's default is overriden, a's default is preserved
\d parted_notnull_inh_test1
diff --git a/src/test/regress/expected/create_table_like.out b/src/test/regress/expected/create_table_like.out
index 2a063a8..94d4858 100644
--- a/src/test/regress/expected/create_table_like.out
+++ b/src/test/regress/expected/create_table_like.out
@@ -90,7 +90,7 @@ CREATE TABLE test_like_id_2 (LIKE test_like_id_1);
b | text | | |
INSERT INTO test_like_id_2 (b) VALUES ('b2');
-ERROR: null value in column "a" violates not-null constraint
+ERROR: null value in column "a" of relation "test_like_id_2" violates not-null constraint
DETAIL: Failing row contains (null, b2).
SELECT * FROM test_like_id_2; -- identity was not copied
a | b
diff --git a/src/test/regress/expected/domain.out b/src/test/regress/expected/domain.out
index 4ff1b4a..2a033a6 100644
--- a/src/test/regress/expected/domain.out
+++ b/src/test/regress/expected/domain.out
@@ -542,12 +542,12 @@ ERROR: domain dnotnull does not allow null values
INSERT INTO nulltest values ('a', NULL, 'c', 'd', 'c');
ERROR: domain dnotnull does not allow null values
INSERT INTO nulltest values ('a', 'b', NULL, 'd', 'c');
-ERROR: null value in column "col3" violates not-null constraint
+ERROR: null value in column "col3" of relation "nulltest" violates not-null constraint
DETAIL: Failing row contains (a, b, null, d, c).
INSERT INTO nulltest values ('a', 'b', 'c', NULL, 'd'); -- Good
-- Test copy
COPY nulltest FROM stdin; --fail
-ERROR: null value in column "col3" violates not-null constraint
+ERROR: null value in column "col3" of relation "nulltest" violates not-null constraint
DETAIL: Failing row contains (a, b, null, d, d).
CONTEXT: COPY nulltest, line 1: "a b \N d d"
COPY nulltest FROM stdin; --fail
@@ -601,14 +601,14 @@ create table defaulttest
, col8 ddef5
);
insert into defaulttest(col4) values(0); -- fails, col5 defaults to null
-ERROR: null value in column "col5" violates not-null constraint
+ERROR: null value in column "col5" of relation "defaulttest" violates not-null constraint
DETAIL: Failing row contains (3, 12, 5, 0, null, 88, 8000, 12.12).
alter table defaulttest alter column col5 drop default;
insert into defaulttest default values; -- succeeds, inserts domain default
-- We used to treat SET DEFAULT NULL as equivalent to DROP DEFAULT; wrong
alter table defaulttest alter column col5 set default null;
insert into defaulttest(col4) values(0); -- fails
-ERROR: null value in column "col5" violates not-null constraint
+ERROR: null value in column "col5" of relation "defaulttest" violates not-null constraint
DETAIL: Failing row contains (3, 12, 5, 0, null, 88, 8000, 12.12).
alter table defaulttest alter column col5 drop default;
insert into defaulttest default values;
diff --git a/src/test/regress/expected/generated.out b/src/test/regress/expected/generated.out
index a6d3670..620579a 100644
--- a/src/test/regress/expected/generated.out
+++ b/src/test/regress/expected/generated.out
@@ -406,24 +406,24 @@ CREATE TABLE gtest20a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STOR
INSERT INTO gtest20a (a) VALUES (10);
INSERT INTO gtest20a (a) VALUES (30);
ALTER TABLE gtest20a ADD CHECK (b < 50); -- fails on existing row
-ERROR: check constraint "gtest20a_b_check" is violated by some row
+ERROR: check constraint "gtest20a_b_check" of relation "gtest20a" is violated by some row
CREATE TABLE gtest20b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STORED);
INSERT INTO gtest20b (a) VALUES (10);
INSERT INTO gtest20b (a) VALUES (30);
ALTER TABLE gtest20b ADD CONSTRAINT chk CHECK (b < 50) NOT VALID;
ALTER TABLE gtest20b VALIDATE CONSTRAINT chk; -- fails on existing row
-ERROR: check constraint "chk" is violated by some row
+ERROR: check constraint "chk" of relation "gtest20b" is violated by some row
-- not-null constraints
CREATE TABLE gtest21a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (nullif(a, 0)) STORED NOT NULL);
INSERT INTO gtest21a (a) VALUES (1); -- ok
INSERT INTO gtest21a (a) VALUES (0); -- violates constraint
-ERROR: null value in column "b" violates not-null constraint
+ERROR: null value in column "b" of relation "gtest21a" violates not-null constraint
DETAIL: Failing row contains (0, null).
CREATE TABLE gtest21b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (nullif(a, 0)) STORED);
ALTER TABLE gtest21b ALTER COLUMN b SET NOT NULL;
INSERT INTO gtest21b (a) VALUES (1); -- ok
INSERT INTO gtest21b (a) VALUES (0); -- violates constraint
-ERROR: null value in column "b" violates not-null constraint
+ERROR: null value in column "b" of relation "gtest21b" violates not-null constraint
DETAIL: Failing row contains (0, null).
ALTER TABLE gtest21b ALTER COLUMN b DROP NOT NULL;
INSERT INTO gtest21b (a) VALUES (0); -- ok now
diff --git a/src/test/regress/expected/identity.out b/src/test/regress/expected/identity.out
index 1a614b8..7322b28 100644
--- a/src/test/regress/expected/identity.out
+++ b/src/test/regress/expected/identity.out
@@ -186,7 +186,7 @@ ERROR: column "a" of relation "itest4" is not an identity column
ALTER TABLE itest4 ALTER COLUMN a DROP IDENTITY IF EXISTS; -- noop
NOTICE: column "a" of relation "itest4" is not an identity column, skipping
INSERT INTO itest4 DEFAULT VALUES; -- fails because NOT NULL is not dropped
-ERROR: null value in column "a" violates not-null constraint
+ERROR: null value in column "a" of relation "itest4" violates not-null constraint
DETAIL: Failing row contains (null, ).
ALTER TABLE itest4 ALTER COLUMN a DROP NOT NULL;
INSERT INTO itest4 DEFAULT VALUES;
@@ -414,7 +414,7 @@ INSERT INTO itest8 VALUES(0), (1);
ALTER TABLE itest8
ADD COLUMN f22 int NOT NULL,
ALTER COLUMN f22 ADD GENERATED ALWAYS AS IDENTITY;
-ERROR: column "f22" contains null values
+ERROR: column "f22" of relation "itest8" contains null values
TABLE itest8;
f1 | f2 | f3 | f4 | f5
----+----+----+----+----
diff --git a/src/test/regress/expected/index_including.out b/src/test/regress/expected/index_including.out
index 2405709..8e5d53e 100644
--- a/src/test/regress/expected/index_including.out
+++ b/src/test/regress/expected/index_including.out
@@ -124,7 +124,7 @@ INSERT INTO tbl SELECT 1, 2, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS x
ERROR: duplicate key value violates unique constraint "covering"
DETAIL: Key (c1, c2)=(1, 2) already exists.
INSERT INTO tbl SELECT 1, NULL, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS x;
-ERROR: null value in column "c2" violates not-null constraint
+ERROR: null value in column "c2" of relation "tbl" violates not-null constraint
DETAIL: Failing row contains (1, null, 3, (4,4),(4,4)).
INSERT INTO tbl SELECT x, 2*x, NULL, NULL FROM generate_series(1,300) AS x;
explain (costs off)
@@ -202,7 +202,7 @@ INSERT INTO tbl SELECT 1, 2, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS x
ERROR: duplicate key value violates unique constraint "tbl_pkey"
DETAIL: Key (c1, c2)=(1, 2) already exists.
INSERT INTO tbl SELECT 1, NULL, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS x;
-ERROR: null value in column "c2" violates not-null constraint
+ERROR: null value in column "c2" of relation "tbl" violates not-null constraint
DETAIL: Failing row contains (1, null, 3, (4,4),(4,4)).
INSERT INTO tbl SELECT x, 2*x, NULL, NULL FROM generate_series(1,10) AS x;
DROP TABLE tbl;
diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out
index d8f56d2..dfd0ee4 100644
--- a/src/test/regress/expected/inherit.out
+++ b/src/test/regress/expected/inherit.out
@@ -537,7 +537,7 @@ SELECT relname, d.* FROM ONLY d, pg_class where d.tableoid = pg_class.oid;
-- Confirm PRIMARY KEY adds NOT NULL constraint to child table
CREATE TEMP TABLE z (b TEXT, PRIMARY KEY(aa, b)) inherits (a);
INSERT INTO z VALUES (NULL, 'text'); -- should fail
-ERROR: null value in column "aa" violates not-null constraint
+ERROR: null value in column "aa" of relation "z" violates not-null constraint
DETAIL: Failing row contains (null, text).
-- Check inherited UPDATE with all children excluded
create table some_tab (a int, b int);
@@ -940,9 +940,9 @@ create table p2(f2 int);
create table c1(f3 int) inherits(p1,p2);
insert into c1 values(1,-1,2);
alter table p2 add constraint cc check (f2>0); -- fail
-ERROR: check constraint "cc" is violated by some row
+ERROR: check constraint "cc" of relation "c1" is violated by some row
alter table p2 add check (f2>0); -- check it without a name, too
-ERROR: check constraint "p2_f2_check" is violated by some row
+ERROR: check constraint "p2_f2_check" of relation "c1" is violated by some row
delete from c1;
insert into c1 values(1,1,2);
alter table p2 add check (f2>0);
diff --git a/src/test/regress/expected/insert.out b/src/test/regress/expected/insert.out
index 75e25cd..45d77ba 100644
--- a/src/test/regress/expected/insert.out
+++ b/src/test/regress/expected/insert.out
@@ -3,7 +3,7 @@
--
create table inserttest (col1 int4, col2 int4 NOT NULL, col3 text default 'testing');
insert into inserttest (col1, col2, col3) values (DEFAULT, DEFAULT, DEFAULT);
-ERROR: null value in column "col2" violates not-null constraint
+ERROR: null value in column "col2" of relation "inserttest" violates not-null constraint
DETAIL: Failing row contains (null, null, testing).
insert into inserttest (col2, col3) values (3, DEFAULT);
insert into inserttest (col1, col2, col3) values (DEFAULT, 5, DEFAULT);
diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
index 0ddbd8e..6674f26 100644
--- a/src/test/regress/expected/privileges.out
+++ b/src/test/regress/expected/privileges.out
@@ -592,13 +592,13 @@ ERROR: duplicate key value violates unique constraint "t1_pkey"
UPDATE t1 SET c2 = 1; -- fail, but row not shown
ERROR: duplicate key value violates unique constraint "t1_pkey"
INSERT INTO t1 (c1, c2) VALUES (null, null); -- fail, but see columns being inserted
-ERROR: null value in column "c1" violates not-null constraint
+ERROR: null value in column "c1" of relation "t1" violates not-null constraint
DETAIL: Failing row contains (c1, c2) = (null, null).
INSERT INTO t1 (c3) VALUES (null); -- fail, but see columns being inserted or have SELECT
-ERROR: null value in column "c1" violates not-null constraint
+ERROR: null value in column "c1" of relation "t1" violates not-null constraint
DETAIL: Failing row contains (c1, c3) = (null, null).
INSERT INTO t1 (c1) VALUES (5); -- fail, but see columns being inserted or have SELECT
-ERROR: null value in column "c2" violates not-null constraint
+ERROR: null value in column "c2" of relation "t1" violates not-null constraint
DETAIL: Failing row contains (c1) = (5).
UPDATE t1 SET c3 = 10; -- fail, but see columns with SELECT rights, or being modified
ERROR: new row for relation "t1" violates check constraint "t1_c3_check"
diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 7cb7467..44c1304 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -100,7 +100,7 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
(1 row)
INSERT INTO reloptions_test VALUES (1, NULL), (NULL, NULL);
-ERROR: null value in column "i" violates not-null constraint
+ERROR: null value in column "i" of relation "reloptions_test" violates not-null constraint
DETAIL: Failing row contains (null, null).
VACUUM reloptions_test;
SELECT pg_relation_size('reloptions_test') > 0;
@@ -125,7 +125,7 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
(1 row)
INSERT INTO reloptions_test VALUES (1, NULL), (NULL, NULL);
-ERROR: null value in column "i" violates not-null constraint
+ERROR: null value in column "i" of relation "reloptions_test" violates not-null constraint
DETAIL: Failing row contains (null, null).
VACUUM reloptions_test;
SELECT pg_relation_size('reloptions_test') = 0;
diff --git a/src/test/regress/expected/sequence.out b/src/test/regress/expected/sequence.out
index 75eb501..8b928b2 100644
--- a/src/test/regress/expected/sequence.out
+++ b/src/test/regress/expected/sequence.out
@@ -69,7 +69,7 @@ INSERT INTO serialTest1 VALUES ('foo');
INSERT INTO serialTest1 VALUES ('bar');
INSERT INTO serialTest1 VALUES ('force', 100);
INSERT INTO serialTest1 VALUES ('wrong', NULL);
-ERROR: null value in column "f2" violates not-null constraint
+ERROR: null value in column "f2" of relation "serialtest1" violates not-null constraint
DETAIL: Failing row contains (wrong, null).
SELECT * FROM serialTest1;
f1 | f2
diff --git a/src/test/regress/expected/vacuum.out b/src/test/regress/expected/vacuum.out
index f4250a4..0cfe28e 100644
--- a/src/test/regress/expected/vacuum.out
+++ b/src/test/regress/expected/vacuum.out
@@ -164,7 +164,7 @@ VACUUM (INDEX_CLEANUP FALSE, FREEZE TRUE) vaccluster;
CREATE TABLE vac_truncate_test(i INT NOT NULL, j text)
WITH (vacuum_truncate=true, autovacuum_enabled=false);
INSERT INTO vac_truncate_test VALUES (1, NULL), (NULL, NULL);
-ERROR: null value in column "i" violates not-null constraint
+ERROR: null value in column "i" of relation "vac_truncate_test" violates not-null constraint
DETAIL: Failing row contains (null, null).
VACUUM (TRUNCATE FALSE) vac_truncate_test;
SELECT pg_relation_size('vac_truncate_test') > 0;
--
1.8.3.1
[application/octet-stream] v4_0003_updated-constraints.source-file.patch (1.4K, ../../CAKYtNAo9Nf0us=hzDKd7WbMxMvXx6mPcCOkhQXVOsH9U-8qw9A@mail.gmail.com/4-v4_0003_updated-constraints.source-file.patch)
download | inline diff:
From 93566ebdab8cb7e76d9f22fd91bedc04977b8750 Mon Sep 17 00:00:00 2001
From: Mahendra Singh Thalor <[email protected]>
Date: Thu, 23 Jan 2020 17:04:48 +0530
Subject: [PATCH 3/3] updated constraints.source file
---
src/test/regress/output/constraints.source | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/test/regress/output/constraints.source b/src/test/regress/output/constraints.source
index e27caed..b727c61 100644
--- a/src/test/regress/output/constraints.source
+++ b/src/test/regress/output/constraints.source
@@ -377,7 +377,7 @@ DETAIL: Key (i)=(1) already exists.
INSERT INTO PRIMARY_TBL VALUES (4, 'three');
INSERT INTO PRIMARY_TBL VALUES (5, 'one');
INSERT INTO PRIMARY_TBL (t) VALUES ('six');
-ERROR: null value in column "i" violates not-null constraint
+ERROR: null value in column "i" of relation "primary_tbl" violates not-null constraint
DETAIL: Failing row contains (null, six).
SELECT '' AS four, * FROM PRIMARY_TBL;
four | i | t
@@ -397,7 +397,7 @@ INSERT INTO PRIMARY_TBL VALUES (1, 'three');
INSERT INTO PRIMARY_TBL VALUES (4, 'three');
INSERT INTO PRIMARY_TBL VALUES (5, 'one');
INSERT INTO PRIMARY_TBL (t) VALUES ('six');
-ERROR: null value in column "i" violates not-null constraint
+ERROR: null value in column "i" of relation "primary_tbl" violates not-null constraint
DETAIL: Failing row contains (null, six).
SELECT '' AS three, * FROM PRIMARY_TBL;
three | i | t
--
1.8.3.1
^ permalink raw reply [nested|flat] 1934+ messages in thread
* Re: Error message inconsistency
@ 2020-01-24 05:21 Amit Kapila <[email protected]>
parent: Mahendra Singh Thalor <[email protected]>
0 siblings, 2 replies; 1934+ messages in thread
From: Amit Kapila @ 2020-01-24 05:21 UTC (permalink / raw)
To: Mahendra Singh Thalor <[email protected]>; +Cc: Tom Lane <[email protected]>; Alvaro Herrera <[email protected]>; MBeena Emerson <[email protected]>; Simon Riggs <[email protected]>; Fabrízio Mello <[email protected]>; PostgreSQL Hackers <[email protected]>
On Thu, Jan 23, 2020 at 5:51 PM Mahendra Singh Thalor
<[email protected]> wrote:
>
> I fixed above comment and updated expected .out files. Attaching
> updated patches.
>
LGTM. I have combined them into the single patch. What do we think
about backpatching this? As there are quite a few changes in the
regression tests, so it might be a good idea to keep the back branches
code in sync, but, OTOH, this is more of a change related to providing
more information, so we don't have any pressing need to backpatch
this. What do others think?
One thing to note is that there are places in code where we use
'table' instead of 'relation' for the same thing in the error messages
as seen in the below places (the first one uses 'relation', the second
one uses 'table') and the patch is using 'relation' which I think is
fine.
1. src/backend/executor/execPartition.c
342 ereport(ERROR,
343 (errcode(ERRCODE_CHECK_VIOLATION),
344 errmsg("no partition of relation \"%s\"
found for row",
345 RelationGetRelationName(rel)),
346 val_desc ?
347 errdetail("Partition key of the failing row
contains %s.",
348 val_desc) : 0));
2. src/backend/commands/typecmds.c
2396 ereport(ERROR,
2397 (errcode(ERRCODE_NOT_NULL_VIOLATION),
2398 errmsg("column \"%s\" of table
\"%s\" contains null values",
2399 NameStr(attr->attname),
2400 RelationGetRelationName(testrel)),
2401 errtablecol(testrel, attnum)));
--
With Regards,
Amit Kapila.
EnterpriseDB: http://www.enterprisedb.com
Attachments:
[application/octet-stream] v5-0001-Added-relation-name-in-error-messages-for-constraint.patch (37.0K, ../../CAA4eK1KTdFmPQwJcE_mJjOSAoix_Kmv25D8xm_NTze=R8qHg8Q@mail.gmail.com/2-v5-0001-Added-relation-name-in-error-messages-for-constraint.patch)
download | inline diff:
From 1853e30caa5d21d2e1711374d8e8f4281cc5cbe1 Mon Sep 17 00:00:00 2001
From: Amit Kapila <[email protected]>
Date: Fri, 24 Jan 2020 10:39:08 +0530
Subject: [PATCH] Added relation name in error messages for constraint checks.
This gives more information to the user about the error and it makes such
messages consistent with the other similar messages in the code.
Reported-by: Simon Riggs
Author: Mahendra Singh and Simon Riggs
Reviewed-by: Beena Emerson and Amit Kapila
Discussion: https://postgr.es/m/CANP8+j+7YUvQvGxTrCiw77R23enMJ7DFmyA3buR+fa2pKs4XhA@mail.gmail.com
---
src/backend/commands/tablecmds.c | 21 ++++---
src/backend/executor/execMain.c | 5 +-
src/test/regress/expected/alter_table.out | 76 ++++++++++++-------------
src/test/regress/expected/copy2.out | 2 +-
src/test/regress/expected/create_table.out | 2 +-
src/test/regress/expected/create_table_like.out | 2 +-
src/test/regress/expected/domain.out | 8 +--
src/test/regress/expected/generated.out | 8 +--
src/test/regress/expected/identity.out | 4 +-
src/test/regress/expected/index_including.out | 4 +-
src/test/regress/expected/inherit.out | 6 +-
src/test/regress/expected/insert.out | 2 +-
src/test/regress/expected/privileges.out | 6 +-
src/test/regress/expected/reloptions.out | 4 +-
src/test/regress/expected/sequence.out | 2 +-
src/test/regress/expected/vacuum.out | 2 +-
src/test/regress/output/constraints.source | 4 +-
17 files changed, 82 insertions(+), 76 deletions(-)
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 7c23968..70589dd 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -5288,8 +5288,9 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
ereport(ERROR,
(errcode(ERRCODE_NOT_NULL_VIOLATION),
- errmsg("column \"%s\" contains null values",
- NameStr(attr->attname)),
+ errmsg("column \"%s\" of relation \"%s\" contains null values",
+ NameStr(attr->attname),
+ RelationGetRelationName(oldrel)),
errtablecol(oldrel, attn + 1)));
}
}
@@ -5304,8 +5305,9 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
if (!ExecCheck(con->qualstate, econtext))
ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION),
- errmsg("check constraint \"%s\" is violated by some row",
- con->name),
+ errmsg("check constraint \"%s\" of relation \"%s\" is violated by some row",
+ con->name,
+ RelationGetRelationName(oldrel)),
errtableconstraint(oldrel, con->name)));
break;
case CONSTR_FOREIGN:
@@ -5322,11 +5324,13 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
if (tab->validate_default)
ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION),
- errmsg("updated partition constraint for default partition would be violated by some row")));
+ errmsg("updated partition constraint for default partition \"%s\" would be violated by some row",
+ RelationGetRelationName(oldrel))));
else
ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION),
- errmsg("partition constraint is violated by some row")));
+ errmsg("partition constraint of relation \"%s\" is violated by some row",
+ RelationGetRelationName(oldrel))));
}
/* Write the tuple out to the new relation */
@@ -10160,8 +10164,9 @@ validateCheckConstraint(Relation rel, HeapTuple constrtup)
if (!ExecCheck(exprstate, econtext))
ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION),
- errmsg("check constraint \"%s\" is violated by some row",
- NameStr(constrForm->conname)),
+ errmsg("check constraint \"%s\" of relation \"%s\" is violated by some row",
+ NameStr(constrForm->conname),
+ RelationGetRelationName(rel)),
errtableconstraint(rel, NameStr(constrForm->conname))));
ResetExprContext(econtext);
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index b03e02a..3a9ce99 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -1957,8 +1957,9 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
ereport(ERROR,
(errcode(ERRCODE_NOT_NULL_VIOLATION),
- errmsg("null value in column \"%s\" violates not-null constraint",
- NameStr(att->attname)),
+ errmsg("null value in column \"%s\" of relation \"%s\" violates not-null constraint",
+ NameStr(att->attname),
+ RelationGetRelationName(orig_rel)),
val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
errtablecol(orig_rel, attrChk)));
}
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index 4dd3507..e73ce4b 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -457,10 +457,10 @@ ALTER TABLE attmp3 validate constraint attmpconstr;
ALTER TABLE attmp3 validate constraint attmpconstr;
-- Try a non-verified CHECK constraint
ALTER TABLE attmp3 ADD CONSTRAINT b_greater_than_ten CHECK (b > 10); -- fail
-ERROR: check constraint "b_greater_than_ten" is violated by some row
+ERROR: check constraint "b_greater_than_ten" of relation "attmp3" is violated by some row
ALTER TABLE attmp3 ADD CONSTRAINT b_greater_than_ten CHECK (b > 10) NOT VALID; -- succeeds
ALTER TABLE attmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- fails
-ERROR: check constraint "b_greater_than_ten" is violated by some row
+ERROR: check constraint "b_greater_than_ten" of relation "attmp3" is violated by some row
DELETE FROM attmp3 WHERE NOT b > 10;
ALTER TABLE attmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- succeeds
ALTER TABLE attmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- succeeds
@@ -476,7 +476,7 @@ CREATE TABLE attmp7 () INHERITS (attmp3);
INSERT INTO attmp6 VALUES (6, 30), (7, 16);
ALTER TABLE attmp3 ADD CONSTRAINT b_le_20 CHECK (b <= 20) NOT VALID;
ALTER TABLE attmp3 VALIDATE CONSTRAINT b_le_20; -- fails
-ERROR: check constraint "b_le_20" is violated by some row
+ERROR: check constraint "b_le_20" of relation "attmp6" is violated by some row
DELETE FROM attmp6 WHERE b > 20;
ALTER TABLE attmp3 VALIDATE CONSTRAINT b_le_20; -- succeeds
-- An already validated constraint must not be revalidated
@@ -497,7 +497,7 @@ insert into child_noinh_convalid values (1);
alter table parent_noinh_convalid add constraint check_a_is_2 check (a = 2) no inherit not valid;
-- fail, because of the row in parent
alter table parent_noinh_convalid validate constraint check_a_is_2;
-ERROR: check constraint "check_a_is_2" is violated by some row
+ERROR: check constraint "check_a_is_2" of relation "parent_noinh_convalid" is violated by some row
delete from only parent_noinh_convalid;
-- ok (parent itself contains no violating rows)
alter table parent_noinh_convalid validate constraint check_a_is_2;
@@ -754,7 +754,7 @@ create table atacc1 ( test int );
insert into atacc1 (test) values (2);
-- add a check constraint (fails)
alter table atacc1 add constraint atacc_test1 check (test>3);
-ERROR: check constraint "atacc_test1" is violated by some row
+ERROR: check constraint "atacc_test1" of relation "atacc1" is violated by some row
insert into atacc1 (test) values (4);
drop table atacc1;
-- let's do one where the check fails because the column doesn't exist
@@ -867,7 +867,7 @@ DETAIL: Failing row contains (-3).
insert into atacc1 (test) values (3);
-- fail, violating row:
alter table atacc2 add constraint foo check (test>0) no inherit;
-ERROR: check constraint "foo" is violated by some row
+ERROR: check constraint "foo" of relation "atacc2" is violated by some row
drop table atacc2;
drop table atacc1;
-- test unique constraint adding
@@ -943,7 +943,7 @@ DETAIL: Key (test)=(2) already exists.
insert into atacc1 (test) values (4);
-- inserting NULL should fail
insert into atacc1 (test) values(NULL);
-ERROR: null value in column "test" violates not-null constraint
+ERROR: null value in column "test" of relation "atacc1" violates not-null constraint
DETAIL: Failing row contains (4, null).
-- try adding a second primary key (should fail)
alter table atacc1 add constraint atacc_oid1 primary key(id);
@@ -970,7 +970,7 @@ create table atacc1 ( test int );
insert into atacc1 (test) values (NULL);
-- add a primary key (fails)
alter table atacc1 add constraint atacc_test1 primary key (test);
-ERROR: column "test" contains null values
+ERROR: column "test" of relation "atacc1" contains null values
insert into atacc1 (test) values (3);
drop table atacc1;
-- let's do one where the primary key constraint fails
@@ -986,7 +986,7 @@ create table atacc1 ( test int );
insert into atacc1 (test) values (0);
-- add a primary key column without a default (fails).
alter table atacc1 add column test2 int primary key;
-ERROR: column "test2" contains null values
+ERROR: column "test2" of relation "atacc1" contains null values
-- now add a primary key column with a default (succeeds).
alter table atacc1 add column test2 int default 0 primary key;
drop table atacc1;
@@ -1011,13 +1011,13 @@ insert into atacc1 (test,test2) values (4,4);
ERROR: duplicate key value violates unique constraint "atacc_test1"
DETAIL: Key (test, test2)=(4, 4) already exists.
insert into atacc1 (test,test2) values (NULL,3);
-ERROR: null value in column "test" violates not-null constraint
+ERROR: null value in column "test" of relation "atacc1" violates not-null constraint
DETAIL: Failing row contains (null, 3).
insert into atacc1 (test,test2) values (3, NULL);
-ERROR: null value in column "test2" violates not-null constraint
+ERROR: null value in column "test2" of relation "atacc1" violates not-null constraint
DETAIL: Failing row contains (3, null).
insert into atacc1 (test,test2) values (NULL,NULL);
-ERROR: null value in column "test" violates not-null constraint
+ERROR: null value in column "test" of relation "atacc1" violates not-null constraint
DETAIL: Failing row contains (null, null).
-- should all succeed
insert into atacc1 (test,test2) values (4,5);
@@ -1032,7 +1032,7 @@ insert into atacc1 (test2, test) values (2, 3);
ERROR: duplicate key value violates unique constraint "atacc1_pkey"
DETAIL: Key (test)=(3) already exists.
insert into atacc1 (test2, test) values (1, NULL);
-ERROR: null value in column "test" violates not-null constraint
+ERROR: null value in column "test" of relation "atacc1" violates not-null constraint
DETAIL: Failing row contains (null, 1).
drop table atacc1;
-- alter table / alter column [set/drop] not null tests
@@ -1056,7 +1056,7 @@ alter table atacc1 drop constraint "atacc1_pkey";
alter table atacc1 alter column test drop not null;
insert into atacc1 values (null);
alter table atacc1 alter test set not null;
-ERROR: column "test" contains null values
+ERROR: column "test" of relation "atacc1" contains null values
delete from atacc1;
alter table atacc1 alter test set not null;
-- try altering a non-existent column, should fail
@@ -1078,12 +1078,12 @@ insert into atacc1 values (null, 1);
-- constraint not cover all values, should fail
alter table atacc1 add constraint atacc1_constr_or check(test_a is not null or test_b < 10);
alter table atacc1 alter test_a set not null;
-ERROR: column "test_a" contains null values
+ERROR: column "test_a" of relation "atacc1" contains null values
alter table atacc1 drop constraint atacc1_constr_or;
-- not valid constraint, should fail
alter table atacc1 add constraint atacc1_constr_invalid check(test_a is not null) not valid;
alter table atacc1 alter test_a set not null;
-ERROR: column "test_a" contains null values
+ERROR: column "test_a" of relation "atacc1" contains null values
alter table atacc1 drop constraint atacc1_constr_invalid;
-- with valid constraint
update atacc1 set test_a = 1;
@@ -1095,10 +1095,10 @@ alter table atacc1 alter test_a drop not null;
-- test multiple set not null at same time
-- test_a checked by atacc1_constr_a_valid, test_b should fail by table scan
alter table atacc1 alter test_a set not null, alter test_b set not null;
-ERROR: column "test_b" contains null values
+ERROR: column "test_b" of relation "atacc1" contains null values
-- commands order has no importance
alter table atacc1 alter test_b set not null, alter test_a set not null;
-ERROR: column "test_b" contains null values
+ERROR: column "test_b" of relation "atacc1" contains null values
-- valid one by table scan, one by check constraints
update atacc1 set test_b = 1;
alter table atacc1 alter test_b set not null, alter test_a set not null;
@@ -1112,31 +1112,31 @@ create table parent (a int);
create table child (b varchar(255)) inherits (parent);
alter table parent alter a set not null;
insert into parent values (NULL);
-ERROR: null value in column "a" violates not-null constraint
+ERROR: null value in column "a" of relation "parent" violates not-null constraint
DETAIL: Failing row contains (null).
insert into child (a, b) values (NULL, 'foo');
-ERROR: null value in column "a" violates not-null constraint
+ERROR: null value in column "a" of relation "child" violates not-null constraint
DETAIL: Failing row contains (null, foo).
alter table parent alter a drop not null;
insert into parent values (NULL);
insert into child (a, b) values (NULL, 'foo');
alter table only parent alter a set not null;
-ERROR: column "a" contains null values
+ERROR: column "a" of relation "parent" contains null values
alter table child alter a set not null;
-ERROR: column "a" contains null values
+ERROR: column "a" of relation "child" contains null values
delete from parent;
alter table only parent alter a set not null;
insert into parent values (NULL);
-ERROR: null value in column "a" violates not-null constraint
+ERROR: null value in column "a" of relation "parent" violates not-null constraint
DETAIL: Failing row contains (null).
alter table child alter a set not null;
insert into child (a, b) values (NULL, 'foo');
-ERROR: null value in column "a" violates not-null constraint
+ERROR: null value in column "a" of relation "child" violates not-null constraint
DETAIL: Failing row contains (null, foo).
delete from child;
alter table child alter a set not null;
insert into child (a, b) values (NULL, 'foo');
-ERROR: null value in column "a" violates not-null constraint
+ERROR: null value in column "a" of relation "child" violates not-null constraint
DETAIL: Failing row contains (null, foo).
drop table child;
drop table parent;
@@ -1474,7 +1474,7 @@ insert into atacc1(value) values (100);
ERROR: new row for relation "atacc1" violates check constraint "atacc1_value_check"
DETAIL: Failing row contains (2, 100).
insert into atacc1(id, value) values (null, 0);
-ERROR: null value in column "id" violates not-null constraint
+ERROR: null value in column "id" of relation "atacc1" violates not-null constraint
DETAIL: Failing row contains (null, 0).
drop table atacc1;
-- test inheritance
@@ -3804,7 +3804,7 @@ CREATE TABLE list_parted2 (
CREATE TABLE part_2 (LIKE list_parted2);
INSERT INTO part_2 VALUES (3, 'a');
ALTER TABLE list_parted2 ATTACH PARTITION part_2 FOR VALUES IN (2);
-ERROR: partition constraint is violated by some row
+ERROR: partition constraint of relation "part_2" is violated by some row
-- should be ok after deleting the bad row
DELETE FROM part_2;
ALTER TABLE list_parted2 ATTACH PARTITION part_2 FOR VALUES IN (2);
@@ -3813,7 +3813,7 @@ CREATE TABLE list_parted2_def PARTITION OF list_parted2 DEFAULT;
INSERT INTO list_parted2_def VALUES (11, 'z');
CREATE TABLE part_3 (LIKE list_parted2);
ALTER TABLE list_parted2 ATTACH PARTITION part_3 FOR VALUES IN (11);
-ERROR: updated partition constraint for default partition would be violated by some row
+ERROR: updated partition constraint for default partition "list_parted2_def" would be violated by some row
-- should be ok after deleting the bad row
DELETE FROM list_parted2_def WHERE a = 11;
ALTER TABLE list_parted2 ATTACH PARTITION part_3 FOR VALUES IN (11);
@@ -3847,7 +3847,7 @@ CREATE TABLE part1 (
INSERT INTO part1 VALUES (1, 10);
-- Remember the TO bound is exclusive
ALTER TABLE range_parted ATTACH PARTITION part1 FOR VALUES FROM (1, 1) TO (1, 10);
-ERROR: partition constraint is violated by some row
+ERROR: partition constraint of relation "part1" is violated by some row
-- should be ok after deleting the bad row
DELETE FROM part1;
ALTER TABLE range_parted ATTACH PARTITION part1 FOR VALUES FROM (1, 1) TO (1, 10);
@@ -3868,7 +3868,7 @@ ERROR: partition "partr_def2" conflicts with existing default partition "partr_
INSERT INTO partr_def1 VALUES (2, 10);
CREATE TABLE part3 (LIKE range_parted);
ALTER TABLE range_parted ATTACH partition part3 FOR VALUES FROM (2, 10) TO (2, 20);
-ERROR: updated partition constraint for default partition would be violated by some row
+ERROR: updated partition constraint for default partition "partr_def1" would be violated by some row
-- Attaching partitions should be successful when there are no overlapping rows
ALTER TABLE range_parted ATTACH partition part3 FOR VALUES FROM (3, 10) TO (3, 20);
-- check that leaf partitions are scanned when attaching a partitioned
@@ -3880,7 +3880,7 @@ CREATE TABLE part_5 (
CREATE TABLE part_5_a PARTITION OF part_5 FOR VALUES IN ('a');
INSERT INTO part_5_a (a, b) VALUES (6, 'a');
ALTER TABLE list_parted2 ATTACH PARTITION part_5 FOR VALUES IN (5);
-ERROR: partition constraint is violated by some row
+ERROR: partition constraint of relation "part_5_a" is violated by some row
-- delete the faulting row and also add a constraint to skip the scan
DELETE FROM part_5_a WHERE a NOT IN (3);
ALTER TABLE part_5 ADD CONSTRAINT check_a CHECK (a IS NOT NULL AND a = 5);
@@ -3931,7 +3931,7 @@ SELECT tableoid::regclass, a, b FROM part_7 order by a;
(2 rows)
ALTER TABLE list_parted2 ATTACH PARTITION part_7 FOR VALUES IN (7);
-ERROR: partition constraint is violated by some row
+ERROR: partition constraint of relation "part_7_a_null" is violated by some row
-- check that leaf partitions of default partition are scanned when
-- attaching a partitioned table.
ALTER TABLE part_5 DROP CONSTRAINT check_a;
@@ -3940,7 +3940,7 @@ CREATE TABLE part5_def_p1 PARTITION OF part5_def FOR VALUES IN (5);
INSERT INTO part5_def_p1 VALUES (5, 'y');
CREATE TABLE part5_p1 (LIKE part_5);
ALTER TABLE part_5 ATTACH PARTITION part5_p1 FOR VALUES IN ('y');
-ERROR: updated partition constraint for default partition would be violated by some row
+ERROR: updated partition constraint for default partition "part5_def_p1" would be violated by some row
-- should be ok after deleting the bad row
DELETE FROM part5_def_p1 WHERE b = 'y';
ALTER TABLE part_5 ATTACH PARTITION part5_p1 FOR VALUES IN ('y');
@@ -3992,7 +3992,7 @@ DROP TABLE fail_part;
CREATE TABLE hpart_2 (LIKE hash_parted);
INSERT INTO hpart_2 VALUES (3, 0);
ALTER TABLE hash_parted ATTACH PARTITION hpart_2 FOR VALUES WITH (MODULUS 4, REMAINDER 1);
-ERROR: partition constraint is violated by some row
+ERROR: partition constraint of relation "hpart_2" is violated by some row
-- should be ok after deleting the bad row
DELETE FROM hpart_2;
ALTER TABLE hash_parted ATTACH PARTITION hpart_2 FOR VALUES WITH (MODULUS 4, REMAINDER 1);
@@ -4005,7 +4005,7 @@ CREATE TABLE hpart_5 (
CREATE TABLE hpart_5_a PARTITION OF hpart_5 FOR VALUES IN ('1', '2', '3');
INSERT INTO hpart_5_a (a, b) VALUES (7, 1);
ALTER TABLE hash_parted ATTACH PARTITION hpart_5 FOR VALUES WITH (MODULUS 4, REMAINDER 2);
-ERROR: partition constraint is violated by some row
+ERROR: partition constraint of relation "hpart_5_a" is violated by some row
-- should be ok after deleting the bad row
DELETE FROM hpart_5_a;
ALTER TABLE hash_parted ATTACH PARTITION hpart_5 FOR VALUES WITH (MODULUS 4, REMAINDER 2);
@@ -4172,7 +4172,7 @@ alter table p1 attach partition p11 for values from (2) to (5);
insert into p1 (a, b) values (2, 3);
-- check that partition validation scan correctly detects violating rows
alter table p attach partition p1 for values from (1, 2) to (1, 10);
-ERROR: partition constraint is violated by some row
+ERROR: partition constraint of relation "p11" is violated by some row
-- cleanup
drop table p;
drop table p1;
@@ -4200,7 +4200,7 @@ insert into defpart_attach_test_d values (1), (2);
-- error because its constraint as the default partition would be violated
-- by the row containing 1
alter table defpart_attach_test attach partition defpart_attach_test_d default;
-ERROR: partition constraint is violated by some row
+ERROR: partition constraint of relation "defpart_attach_test_d" is violated by some row
delete from defpart_attach_test_d where a = 1;
alter table defpart_attach_test_d add check (a > 1);
-- should be attached successfully and without needing to be scanned
@@ -4210,7 +4210,7 @@ alter table defpart_attach_test attach partition defpart_attach_test_d default;
-- successfully
create table defpart_attach_test_2 (like defpart_attach_test_d);
alter table defpart_attach_test attach partition defpart_attach_test_2 for values in (2);
-ERROR: updated partition constraint for default partition would be violated by some row
+ERROR: updated partition constraint for default partition "defpart_attach_test_d" would be violated by some row
drop table defpart_attach_test;
-- check combinations of temporary and permanent relations when attaching
-- partitions.
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index c53ed3e..e40287d 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -440,7 +440,7 @@ SELECT c, d FROM forcetest WHERE a = 2;
-- should fail with not-null constraint violation
BEGIN;
COPY forcetest (a, b, c) FROM STDIN WITH (FORMAT csv, FORCE_NULL(b), FORCE_NOT_NULL(c));
-ERROR: null value in column "b" violates not-null constraint
+ERROR: null value in column "b" of relation "forcetest" violates not-null constraint
DETAIL: Failing row contains (3, null, , null, null).
CONTEXT: COPY forcetest, line 1: "3,,"""
ROLLBACK;
diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out
index b64f919..c5e95ed 100644
--- a/src/test/regress/expected/create_table.out
+++ b/src/test/regress/expected/create_table.out
@@ -955,7 +955,7 @@ CREATE TABLE part_c_1_10 PARTITION OF part_c FOR VALUES FROM (1) TO (10);
create table parted_notnull_inh_test (a int default 1, b int not null default 0) partition by list (a);
create table parted_notnull_inh_test1 partition of parted_notnull_inh_test (a not null, b default 1) for values in (1);
insert into parted_notnull_inh_test (b) values (null);
-ERROR: null value in column "b" violates not-null constraint
+ERROR: null value in column "b" of relation "parted_notnull_inh_test1" violates not-null constraint
DETAIL: Failing row contains (1, null).
-- note that while b's default is overriden, a's default is preserved
\d parted_notnull_inh_test1
diff --git a/src/test/regress/expected/create_table_like.out b/src/test/regress/expected/create_table_like.out
index 2a063a8..94d4858 100644
--- a/src/test/regress/expected/create_table_like.out
+++ b/src/test/regress/expected/create_table_like.out
@@ -90,7 +90,7 @@ CREATE TABLE test_like_id_2 (LIKE test_like_id_1);
b | text | | |
INSERT INTO test_like_id_2 (b) VALUES ('b2');
-ERROR: null value in column "a" violates not-null constraint
+ERROR: null value in column "a" of relation "test_like_id_2" violates not-null constraint
DETAIL: Failing row contains (null, b2).
SELECT * FROM test_like_id_2; -- identity was not copied
a | b
diff --git a/src/test/regress/expected/domain.out b/src/test/regress/expected/domain.out
index 4ff1b4a..2a033a6 100644
--- a/src/test/regress/expected/domain.out
+++ b/src/test/regress/expected/domain.out
@@ -542,12 +542,12 @@ ERROR: domain dnotnull does not allow null values
INSERT INTO nulltest values ('a', NULL, 'c', 'd', 'c');
ERROR: domain dnotnull does not allow null values
INSERT INTO nulltest values ('a', 'b', NULL, 'd', 'c');
-ERROR: null value in column "col3" violates not-null constraint
+ERROR: null value in column "col3" of relation "nulltest" violates not-null constraint
DETAIL: Failing row contains (a, b, null, d, c).
INSERT INTO nulltest values ('a', 'b', 'c', NULL, 'd'); -- Good
-- Test copy
COPY nulltest FROM stdin; --fail
-ERROR: null value in column "col3" violates not-null constraint
+ERROR: null value in column "col3" of relation "nulltest" violates not-null constraint
DETAIL: Failing row contains (a, b, null, d, d).
CONTEXT: COPY nulltest, line 1: "a b \N d d"
COPY nulltest FROM stdin; --fail
@@ -601,14 +601,14 @@ create table defaulttest
, col8 ddef5
);
insert into defaulttest(col4) values(0); -- fails, col5 defaults to null
-ERROR: null value in column "col5" violates not-null constraint
+ERROR: null value in column "col5" of relation "defaulttest" violates not-null constraint
DETAIL: Failing row contains (3, 12, 5, 0, null, 88, 8000, 12.12).
alter table defaulttest alter column col5 drop default;
insert into defaulttest default values; -- succeeds, inserts domain default
-- We used to treat SET DEFAULT NULL as equivalent to DROP DEFAULT; wrong
alter table defaulttest alter column col5 set default null;
insert into defaulttest(col4) values(0); -- fails
-ERROR: null value in column "col5" violates not-null constraint
+ERROR: null value in column "col5" of relation "defaulttest" violates not-null constraint
DETAIL: Failing row contains (3, 12, 5, 0, null, 88, 8000, 12.12).
alter table defaulttest alter column col5 drop default;
insert into defaulttest default values;
diff --git a/src/test/regress/expected/generated.out b/src/test/regress/expected/generated.out
index a6d3670..620579a 100644
--- a/src/test/regress/expected/generated.out
+++ b/src/test/regress/expected/generated.out
@@ -406,24 +406,24 @@ CREATE TABLE gtest20a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STOR
INSERT INTO gtest20a (a) VALUES (10);
INSERT INTO gtest20a (a) VALUES (30);
ALTER TABLE gtest20a ADD CHECK (b < 50); -- fails on existing row
-ERROR: check constraint "gtest20a_b_check" is violated by some row
+ERROR: check constraint "gtest20a_b_check" of relation "gtest20a" is violated by some row
CREATE TABLE gtest20b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STORED);
INSERT INTO gtest20b (a) VALUES (10);
INSERT INTO gtest20b (a) VALUES (30);
ALTER TABLE gtest20b ADD CONSTRAINT chk CHECK (b < 50) NOT VALID;
ALTER TABLE gtest20b VALIDATE CONSTRAINT chk; -- fails on existing row
-ERROR: check constraint "chk" is violated by some row
+ERROR: check constraint "chk" of relation "gtest20b" is violated by some row
-- not-null constraints
CREATE TABLE gtest21a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (nullif(a, 0)) STORED NOT NULL);
INSERT INTO gtest21a (a) VALUES (1); -- ok
INSERT INTO gtest21a (a) VALUES (0); -- violates constraint
-ERROR: null value in column "b" violates not-null constraint
+ERROR: null value in column "b" of relation "gtest21a" violates not-null constraint
DETAIL: Failing row contains (0, null).
CREATE TABLE gtest21b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (nullif(a, 0)) STORED);
ALTER TABLE gtest21b ALTER COLUMN b SET NOT NULL;
INSERT INTO gtest21b (a) VALUES (1); -- ok
INSERT INTO gtest21b (a) VALUES (0); -- violates constraint
-ERROR: null value in column "b" violates not-null constraint
+ERROR: null value in column "b" of relation "gtest21b" violates not-null constraint
DETAIL: Failing row contains (0, null).
ALTER TABLE gtest21b ALTER COLUMN b DROP NOT NULL;
INSERT INTO gtest21b (a) VALUES (0); -- ok now
diff --git a/src/test/regress/expected/identity.out b/src/test/regress/expected/identity.out
index 1a614b8..7322b28 100644
--- a/src/test/regress/expected/identity.out
+++ b/src/test/regress/expected/identity.out
@@ -186,7 +186,7 @@ ERROR: column "a" of relation "itest4" is not an identity column
ALTER TABLE itest4 ALTER COLUMN a DROP IDENTITY IF EXISTS; -- noop
NOTICE: column "a" of relation "itest4" is not an identity column, skipping
INSERT INTO itest4 DEFAULT VALUES; -- fails because NOT NULL is not dropped
-ERROR: null value in column "a" violates not-null constraint
+ERROR: null value in column "a" of relation "itest4" violates not-null constraint
DETAIL: Failing row contains (null, ).
ALTER TABLE itest4 ALTER COLUMN a DROP NOT NULL;
INSERT INTO itest4 DEFAULT VALUES;
@@ -414,7 +414,7 @@ INSERT INTO itest8 VALUES(0), (1);
ALTER TABLE itest8
ADD COLUMN f22 int NOT NULL,
ALTER COLUMN f22 ADD GENERATED ALWAYS AS IDENTITY;
-ERROR: column "f22" contains null values
+ERROR: column "f22" of relation "itest8" contains null values
TABLE itest8;
f1 | f2 | f3 | f4 | f5
----+----+----+----+----
diff --git a/src/test/regress/expected/index_including.out b/src/test/regress/expected/index_including.out
index 2405709..8e5d53e 100644
--- a/src/test/regress/expected/index_including.out
+++ b/src/test/regress/expected/index_including.out
@@ -124,7 +124,7 @@ INSERT INTO tbl SELECT 1, 2, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS x
ERROR: duplicate key value violates unique constraint "covering"
DETAIL: Key (c1, c2)=(1, 2) already exists.
INSERT INTO tbl SELECT 1, NULL, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS x;
-ERROR: null value in column "c2" violates not-null constraint
+ERROR: null value in column "c2" of relation "tbl" violates not-null constraint
DETAIL: Failing row contains (1, null, 3, (4,4),(4,4)).
INSERT INTO tbl SELECT x, 2*x, NULL, NULL FROM generate_series(1,300) AS x;
explain (costs off)
@@ -202,7 +202,7 @@ INSERT INTO tbl SELECT 1, 2, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS x
ERROR: duplicate key value violates unique constraint "tbl_pkey"
DETAIL: Key (c1, c2)=(1, 2) already exists.
INSERT INTO tbl SELECT 1, NULL, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS x;
-ERROR: null value in column "c2" violates not-null constraint
+ERROR: null value in column "c2" of relation "tbl" violates not-null constraint
DETAIL: Failing row contains (1, null, 3, (4,4),(4,4)).
INSERT INTO tbl SELECT x, 2*x, NULL, NULL FROM generate_series(1,10) AS x;
DROP TABLE tbl;
diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out
index d8f56d2..dfd0ee4 100644
--- a/src/test/regress/expected/inherit.out
+++ b/src/test/regress/expected/inherit.out
@@ -537,7 +537,7 @@ SELECT relname, d.* FROM ONLY d, pg_class where d.tableoid = pg_class.oid;
-- Confirm PRIMARY KEY adds NOT NULL constraint to child table
CREATE TEMP TABLE z (b TEXT, PRIMARY KEY(aa, b)) inherits (a);
INSERT INTO z VALUES (NULL, 'text'); -- should fail
-ERROR: null value in column "aa" violates not-null constraint
+ERROR: null value in column "aa" of relation "z" violates not-null constraint
DETAIL: Failing row contains (null, text).
-- Check inherited UPDATE with all children excluded
create table some_tab (a int, b int);
@@ -940,9 +940,9 @@ create table p2(f2 int);
create table c1(f3 int) inherits(p1,p2);
insert into c1 values(1,-1,2);
alter table p2 add constraint cc check (f2>0); -- fail
-ERROR: check constraint "cc" is violated by some row
+ERROR: check constraint "cc" of relation "c1" is violated by some row
alter table p2 add check (f2>0); -- check it without a name, too
-ERROR: check constraint "p2_f2_check" is violated by some row
+ERROR: check constraint "p2_f2_check" of relation "c1" is violated by some row
delete from c1;
insert into c1 values(1,1,2);
alter table p2 add check (f2>0);
diff --git a/src/test/regress/expected/insert.out b/src/test/regress/expected/insert.out
index 75e25cd..45d77ba 100644
--- a/src/test/regress/expected/insert.out
+++ b/src/test/regress/expected/insert.out
@@ -3,7 +3,7 @@
--
create table inserttest (col1 int4, col2 int4 NOT NULL, col3 text default 'testing');
insert into inserttest (col1, col2, col3) values (DEFAULT, DEFAULT, DEFAULT);
-ERROR: null value in column "col2" violates not-null constraint
+ERROR: null value in column "col2" of relation "inserttest" violates not-null constraint
DETAIL: Failing row contains (null, null, testing).
insert into inserttest (col2, col3) values (3, DEFAULT);
insert into inserttest (col1, col2, col3) values (DEFAULT, 5, DEFAULT);
diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
index 0ddbd8e..6674f26 100644
--- a/src/test/regress/expected/privileges.out
+++ b/src/test/regress/expected/privileges.out
@@ -592,13 +592,13 @@ ERROR: duplicate key value violates unique constraint "t1_pkey"
UPDATE t1 SET c2 = 1; -- fail, but row not shown
ERROR: duplicate key value violates unique constraint "t1_pkey"
INSERT INTO t1 (c1, c2) VALUES (null, null); -- fail, but see columns being inserted
-ERROR: null value in column "c1" violates not-null constraint
+ERROR: null value in column "c1" of relation "t1" violates not-null constraint
DETAIL: Failing row contains (c1, c2) = (null, null).
INSERT INTO t1 (c3) VALUES (null); -- fail, but see columns being inserted or have SELECT
-ERROR: null value in column "c1" violates not-null constraint
+ERROR: null value in column "c1" of relation "t1" violates not-null constraint
DETAIL: Failing row contains (c1, c3) = (null, null).
INSERT INTO t1 (c1) VALUES (5); -- fail, but see columns being inserted or have SELECT
-ERROR: null value in column "c2" violates not-null constraint
+ERROR: null value in column "c2" of relation "t1" violates not-null constraint
DETAIL: Failing row contains (c1) = (5).
UPDATE t1 SET c3 = 10; -- fail, but see columns with SELECT rights, or being modified
ERROR: new row for relation "t1" violates check constraint "t1_c3_check"
diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 7cb7467..44c1304 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -100,7 +100,7 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
(1 row)
INSERT INTO reloptions_test VALUES (1, NULL), (NULL, NULL);
-ERROR: null value in column "i" violates not-null constraint
+ERROR: null value in column "i" of relation "reloptions_test" violates not-null constraint
DETAIL: Failing row contains (null, null).
VACUUM reloptions_test;
SELECT pg_relation_size('reloptions_test') > 0;
@@ -125,7 +125,7 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
(1 row)
INSERT INTO reloptions_test VALUES (1, NULL), (NULL, NULL);
-ERROR: null value in column "i" violates not-null constraint
+ERROR: null value in column "i" of relation "reloptions_test" violates not-null constraint
DETAIL: Failing row contains (null, null).
VACUUM reloptions_test;
SELECT pg_relation_size('reloptions_test') = 0;
diff --git a/src/test/regress/expected/sequence.out b/src/test/regress/expected/sequence.out
index 75eb501..8b928b2 100644
--- a/src/test/regress/expected/sequence.out
+++ b/src/test/regress/expected/sequence.out
@@ -69,7 +69,7 @@ INSERT INTO serialTest1 VALUES ('foo');
INSERT INTO serialTest1 VALUES ('bar');
INSERT INTO serialTest1 VALUES ('force', 100);
INSERT INTO serialTest1 VALUES ('wrong', NULL);
-ERROR: null value in column "f2" violates not-null constraint
+ERROR: null value in column "f2" of relation "serialtest1" violates not-null constraint
DETAIL: Failing row contains (wrong, null).
SELECT * FROM serialTest1;
f1 | f2
diff --git a/src/test/regress/expected/vacuum.out b/src/test/regress/expected/vacuum.out
index f4250a4..0cfe28e 100644
--- a/src/test/regress/expected/vacuum.out
+++ b/src/test/regress/expected/vacuum.out
@@ -164,7 +164,7 @@ VACUUM (INDEX_CLEANUP FALSE, FREEZE TRUE) vaccluster;
CREATE TABLE vac_truncate_test(i INT NOT NULL, j text)
WITH (vacuum_truncate=true, autovacuum_enabled=false);
INSERT INTO vac_truncate_test VALUES (1, NULL), (NULL, NULL);
-ERROR: null value in column "i" violates not-null constraint
+ERROR: null value in column "i" of relation "vac_truncate_test" violates not-null constraint
DETAIL: Failing row contains (null, null).
VACUUM (TRUNCATE FALSE) vac_truncate_test;
SELECT pg_relation_size('vac_truncate_test') > 0;
diff --git a/src/test/regress/output/constraints.source b/src/test/regress/output/constraints.source
index e27caed..b727c61 100644
--- a/src/test/regress/output/constraints.source
+++ b/src/test/regress/output/constraints.source
@@ -377,7 +377,7 @@ DETAIL: Key (i)=(1) already exists.
INSERT INTO PRIMARY_TBL VALUES (4, 'three');
INSERT INTO PRIMARY_TBL VALUES (5, 'one');
INSERT INTO PRIMARY_TBL (t) VALUES ('six');
-ERROR: null value in column "i" violates not-null constraint
+ERROR: null value in column "i" of relation "primary_tbl" violates not-null constraint
DETAIL: Failing row contains (null, six).
SELECT '' AS four, * FROM PRIMARY_TBL;
four | i | t
@@ -397,7 +397,7 @@ INSERT INTO PRIMARY_TBL VALUES (1, 'three');
INSERT INTO PRIMARY_TBL VALUES (4, 'three');
INSERT INTO PRIMARY_TBL VALUES (5, 'one');
INSERT INTO PRIMARY_TBL (t) VALUES ('six');
-ERROR: null value in column "i" violates not-null constraint
+ERROR: null value in column "i" of relation "primary_tbl" violates not-null constraint
DETAIL: Failing row contains (null, six).
SELECT '' AS three, * FROM PRIMARY_TBL;
three | i | t
--
1.8.3.1
^ permalink raw reply [nested|flat] 1934+ messages in thread
* Re: Error message inconsistency
@ 2020-01-24 16:07 Tom Lane <[email protected]>
parent: Amit Kapila <[email protected]>
1 sibling, 1 reply; 1934+ messages in thread
From: Tom Lane @ 2020-01-24 16:07 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Mahendra Singh Thalor <[email protected]>; Alvaro Herrera <[email protected]>; MBeena Emerson <[email protected]>; Simon Riggs <[email protected]>; Fabrízio Mello <[email protected]>; PostgreSQL Hackers <[email protected]>
Amit Kapila <[email protected]> writes:
> LGTM. I have combined them into the single patch. What do we think
> about backpatching this?
No objection to the patch for HEAD, but it does not seem like
back-patch material: it is not fixing a bug.
regards, tom lane
^ permalink raw reply [nested|flat] 1934+ messages in thread
* Re: Error message inconsistency
@ 2020-01-25 04:46 Amit Kapila <[email protected]>
parent: Tom Lane <[email protected]>
0 siblings, 1 reply; 1934+ messages in thread
From: Amit Kapila @ 2020-01-25 04:46 UTC (permalink / raw)
To: Tom Lane <[email protected]>; +Cc: Mahendra Singh Thalor <[email protected]>; Alvaro Herrera <[email protected]>; MBeena Emerson <[email protected]>; Simon Riggs <[email protected]>; Fabrízio Mello <[email protected]>; PostgreSQL Hackers <[email protected]>
On Fri, Jan 24, 2020 at 9:37 PM Tom Lane <[email protected]> wrote:
>
> Amit Kapila <[email protected]> writes:
> > LGTM. I have combined them into the single patch. What do we think
> > about backpatching this?
>
> No objection to the patch for HEAD, but it does not seem like
> back-patch material: it is not fixing a bug.
>
Okay, I will commit this early next week (by Tuesday).
--
With Regards,
Amit Kapila.
EnterpriseDB: http://www.enterprisedb.com
^ permalink raw reply [nested|flat] 1934+ messages in thread
* Re: Error message inconsistency
@ 2020-01-27 15:54 Robert Haas <[email protected]>
parent: Amit Kapila <[email protected]>
1 sibling, 0 replies; 1934+ messages in thread
From: Robert Haas @ 2020-01-27 15:54 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Mahendra Singh Thalor <[email protected]>; Tom Lane <[email protected]>; Alvaro Herrera <[email protected]>; MBeena Emerson <[email protected]>; Simon Riggs <[email protected]>; Fabrízio Mello <[email protected]>; PostgreSQL Hackers <[email protected]>
On Fri, Jan 24, 2020 at 12:22 AM Amit Kapila <[email protected]> wrote:
> One thing to note is that there are places in code where we use
> 'table' instead of 'relation' for the same thing in the error messages
> as seen in the below places (the first one uses 'relation', the second
> one uses 'table') and the patch is using 'relation' which I think is
> fine.
We often use "relation" as a sort of a weasel-word when we don't know
the relkind; i.e. when we're complaining about something that might be
a view or index or foreign table or whatever. If we say "table," we
need to know that it is, precisely, a table.
--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 1934+ messages in thread
* Re: Error message inconsistency
@ 2020-01-28 12:43 Amit Kapila <[email protected]>
parent: Amit Kapila <[email protected]>
0 siblings, 1 reply; 1934+ messages in thread
From: Amit Kapila @ 2020-01-28 12:43 UTC (permalink / raw)
To: Tom Lane <[email protected]>; +Cc: Mahendra Singh Thalor <[email protected]>; Alvaro Herrera <[email protected]>; MBeena Emerson <[email protected]>; Simon Riggs <[email protected]>; Fabrízio Mello <[email protected]>; PostgreSQL Hackers <[email protected]>
On Sat, Jan 25, 2020 at 10:16 AM Amit Kapila <[email protected]> wrote:
>
> On Fri, Jan 24, 2020 at 9:37 PM Tom Lane <[email protected]> wrote:
> >
> > Amit Kapila <[email protected]> writes:
> > > LGTM. I have combined them into the single patch. What do we think
> > > about backpatching this?
> >
> > No objection to the patch for HEAD, but it does not seem like
> > back-patch material: it is not fixing a bug.
> >
>
> Okay, I will commit this early next week (by Tuesday).
>
Pushed.
--
With Regards,
Amit Kapila.
EnterpriseDB: http://www.enterprisedb.com
^ permalink raw reply [nested|flat] 1934+ messages in thread
* Re: Error message inconsistency
@ 2020-01-30 05:59 Mahendra Singh Thalor <[email protected]>
parent: Amit Kapila <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Mahendra Singh Thalor @ 2020-01-30 05:59 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Tom Lane <[email protected]>; Alvaro Herrera <[email protected]>; MBeena Emerson <[email protected]>; Simon Riggs <[email protected]>; Fabrízio Mello <[email protected]>; PostgreSQL Hackers <[email protected]>
On Tue, 28 Jan 2020 at 18:13, Amit Kapila <[email protected]> wrote:
>
> On Sat, Jan 25, 2020 at 10:16 AM Amit Kapila <[email protected]> wrote:
> >
> > On Fri, Jan 24, 2020 at 9:37 PM Tom Lane <[email protected]> wrote:
> > >
> > > Amit Kapila <[email protected]> writes:
> > > > LGTM. I have combined them into the single patch. What do we think
> > > > about backpatching this?
> > >
> > > No objection to the patch for HEAD, but it does not seem like
> > > back-patch material: it is not fixing a bug.
> > >
> >
> > Okay, I will commit this early next week (by Tuesday).
> >
>
> Pushed.
>
Thank you for committing it!
--
Thanks and Regards
Mahendra Singh Thalor
EnterpriseDB: http://www.enterprisedb.com
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--=-=-=--
^ permalink raw reply [nested|flat] 1934+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used.
@ 2026-05-06 07:38 Antonin Houska <[email protected]>
0 siblings, 0 replies; 1934+ messages in thread
From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw)
Currently, decoding session that relies on database-specific xl_running_xacts
WAL records can also use some information of cluster-wide records and vice
versa. Although this approach might reduce the total number of
xl_running_xacts records, it's simply not correct.
SnapBuildProcessRunningXacts() now decides at the very beginning whether
particular record can be used or not.
---
src/backend/replication/logical/snapbuild.c | 55 +++++++++++++--------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index c8309b96ed4..b9661b7d70a 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
ReorderBufferTXN *txn;
TransactionId xmin;
+ /*
+ * Each decoding session should use either cluster-wide snapshots or
+ * database-specific ones, but not both. Since the latter can have more
+ * recent value of oldestRunningXid, builder->xmin could go backwards if
+ * it was followed by cluster-wide snapshot - see the ->xmin adjustment
+ * below.
+ */
+ if (!db_specific && OidIsValid(running->dbid))
+ return;
+
+ if (db_specific)
+ {
+ /*
+ * Make sure that we have the snapshots needed for startup, as well as
+ * those for regular cleanup: each time the cluster-wide snapshot is
+ * created (typically on slot creation or by checkpointer), the
+ * database-specific snapshot is requested here if the current session
+ * needs it.
+ */
+ if (!OidIsValid(running->dbid))
+ {
+ LogStandbySnapshot(MyDatabaseId);
+
+ return;
+ }
+ /*
+ * Snapshots issued for other databases do not contain the information
+ * about transactions in our database.
+ */
+ else if (running->dbid != MyDatabaseId)
+ return;
+ }
+
/*
* If we're not consistent yet, inspect the record to see whether it
* allows to get closer to being consistent. If we are consistent, dump
@@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
*/
if (db_specific)
{
- /*
- * If we must only keep track of transactions running in the
- * current database, we need transaction info from exactly that
- * database.
- */
- if (running->dbid != MyDatabaseId)
- {
- LogStandbySnapshot(MyDatabaseId);
-
- return;
- }
+ Assert(running->dbid == MyDatabaseId);
/*
* We'd better be able to check during scan if the plugin does not
@@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact
else
SnapBuildSerialize(builder, lsn);
- /*
- * Database specific transaction info may exist to reach CONSISTENT state
- * faster, however the code below makes no use of it. Moreover, such
- * record might cause problems because the following normal (cluster-wide)
- * record can have lower value of oldestRunningXid. In that case, let's
- * wait with the cleanup for the next regular cluster-wide record.
- */
- if (OidIsValid(running->dbid))
- return;
-
/*
* Update range of interesting xids based on the running xacts
* information. We don't increase ->xmax using it, because once we are in
--
2.47.3
--tbdehtstrqwksfdh--
^ permalink raw reply [nested|flat] 1934+ messages in thread
end of thread, other threads:[~2026-05-06 07:38 UTC | newest]
Thread overview: 1934+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2020-01-06 13:00 Re: Error message inconsistency Mahendra Singh Thalor <[email protected]>
2020-01-09 12:12 ` MBeena Emerson <[email protected]>
2020-01-21 05:19 ` Amit Kapila <[email protected]>
2020-01-21 05:37 ` MBeena Emerson <[email protected]>
2020-01-21 14:39 ` Alvaro Herrera <[email protected]>
2020-01-22 07:39 ` Mahendra Singh Thalor <[email protected]>
2020-01-21 05:21 ` Amit Kapila <[email protected]>
2020-01-22 07:55 ` Mahendra Singh Thalor <[email protected]>
2020-01-22 09:53 ` MBeena Emerson <[email protected]>
2020-01-22 13:32 ` Alvaro Herrera <[email protected]>
2020-01-22 15:18 ` Tom Lane <[email protected]>
2020-01-23 04:50 ` Amit Kapila <[email protected]>
2020-01-23 12:21 ` Mahendra Singh Thalor <[email protected]>
2020-01-24 05:21 ` Amit Kapila <[email protected]>
2020-01-24 16:07 ` Tom Lane <[email protected]>
2020-01-25 04:46 ` Amit Kapila <[email protected]>
2020-01-28 12:43 ` Amit Kapila <[email protected]>
2020-01-30 05:59 ` Mahendra Singh Thalor <[email protected]>
2020-01-27 15:54 ` Robert Haas <[email protected]>
2020-01-23 04:31 ` Amit Kapila <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox